\n"
+ }
+
+ # append page number links for all pages except for this page
+ append photo_nav_html "\t
\n"
+ set i 0
+ set last {}
+ foreach {id i} [pa_pagination_context_ids $cur_id $all_ids 4] {
+ if {![empty_string_p $last] && [expr $last + 1] != $i} {
+ append photo_nav_html "•"
+ }
+ set last $i
+ if { $cur_id == $id } {
+ append photo_nav_html "\t\t$i\n"
+ } else {
+ append photo_nav_html "\t\t$i\n"
+ }
+
+ }
+ append photo_nav_html "\t
\n"
+
+ append photo_nav_html "
\n"
+ return $photo_nav_html
+}
+
+
+ad_proc -public pa_expand_archive {
+ upload_file
+ tmpfile
+ {dest_dir_base "extract"}
+} {
+ Given an uploaded file in file tmpfile with original name upload_file
+ extract the archive and put in a tmp directory which is the return value
+ of the function
+} {
+ set tmp_dir [file join [file dirname $tmpfile] [ns_mktemp "$dest_dir_base-XXXXXX"]]
+ if [catch { ns_mkdir $tmp_dir } errMsg ] {
+ ns_log Notice "expand_archive: Error creating directory $tmp_dir: $errMsg"
+ return -code error "expand_archive: Error creating directory $tmp_dir: $errMsg"
+ }
+
+ set upload_file [string trim [string tolower $upload_file]]
+
+ if {[regexp {(.tar.gz|.tgz)$} $upload_file]} {
+ set type tgz
+ } elseif {[regexp {.tar.z$} $upload_file]} {
+ set type tgZ
+ } elseif {[regexp {.tar$} $upload_file]} {
+ set type tar
+ } elseif {[regexp {(.tar.bz2|.tbz2)$} $upload_file]} {
+ set type tbz2
+ } elseif {[regexp {.zip$} $upload_file]} {
+ set type zip
+ } else {
+ set type "Uknown type"
+ }
+
+ switch $type {
+ tar {
+ set errp [ catch { exec tar --directory $tmp_dir -xvf $tmpfile } errMsg]
+ }
+ tgZ {
+ set errp [ catch { exec tar --directory $tmp_dir -xZvf $tmpfile } errMsg]
+ }
+ tgz {
+ set errp [ catch { exec tar --directory $tmp_dir -xzvf $tmpfile } errMsg]
+ }
+ tbz2 {
+ set errp [ catch { exec tar --directory $tmp_dir -xjvf $tmpfile } errMsg]
+ }
+ zip {
+ set errp [ catch { exec unzip -d $tmp_dir $tmpfile } errMsg]
+ }
+ default {
+ set errp 1
+ set errMsg "Unknown file type. Dont know how to extract $upload_file"
+ }
+ }
+
+ if {$errp} {
+ file delete -force $tmp_dir
+ ns_log Notice "expand_archive: extract type $type failed $errMsg"
+ return -code error "expand_archive: extract type $type failed $errMsg"
+ }
+ return $tmp_dir
+}
+
+ad_proc -public pa_walk {
+ dir
+} {
+ Walk starting at a given directory and return a list
+ of all the plain files found
+} {
+ set files [list]
+ foreach f [glob -nocomplain [file join $dir *]] {
+ set type [file type $f]
+ switch $type {
+ directory {
+ set files [concat $files [pa_walk $f]]
+ }
+ file {
+ lappend files $f
+ }
+ default {
+ # Goofy file types -- just ignore them
+ }
+ }
+ }
+ return $files
+}
+
+ad_proc -public pa_file_info {
+ file
+} {
+ return the image information from a given file
+} {
+ set info [list]
+ if { [catch {set size [file size $file]} errMsg] } {
+ return -code error $errMsg
+ }
+ if { [ catch {set out [exec identify -ping -format "%w %h %m %k %q %#" $file]} errMsg]} {
+ return -code error $errMsg
+ }
+
+ foreach {width height type colors quantum sha256} [split $out { }] {}
+ switch $type {
+ JPG - JPEG {
+ set mime image/jpeg
+ }
+ GIF - GIF87 {
+ set mime image/gif
+ }
+ PNG {
+ set mime image/png
+ }
+ TIF - TIFF {
+ set mime image/tiff
+ }
+ default {
+ set mime {}
+ }
+ }
+
+ return [list $size $width $height $type $mime $colors $quantum $sha256]
+}
+
+
+ad_proc -public pa_insert_image {
+ name
+ photo_id
+ item_id
+ rev_id
+ user_id
+ peeraddr
+ context_id
+ title
+ description
+ mime_type
+ relation
+ is_live
+ path
+ height
+ width
+ size
+} {
+ db_exec_plsql pa_insert_image {
+ declare
+ dummy integer;
+ begin
+
+ dummy := image.new (
+ name => :name,
+ parent_id => :photo_id,
+ item_id => :item_id,
+ revision_id => :rev_id,
+ creation_date => sysdate,
+ creation_user => :user_id,
+ creation_ip => :peeraddr,
+ context_id => :context_id,
+ title => :title,
+ description => :description,
+ mime_type => :mime_type,
+ relation_tag => :relation,
+ is_live => :is_live,
+ path => :path,
+ height => :height,
+ width => :width,
+ file_size => :size
+ );
+ end;
+ }
+}
+
+ad_proc -public pa_load_images {
+ {-remove 0}
+ {-client_name {}}
+ {-strip_prefix {}}
+ {-description {}}
+ {-story {}}
+ {-caption {}}
+ image_files
+ album_id
+ user_id
+} {
+ load a list of files to the provided album owned by user_id
+
+ -remove 1 to delete the file after moving to the content repository
+ -client_name provide the name of the upload file (for individual uploads)
+ -strip_prefix the prefix to remove from the filename (for expanded archives)
+ image_files list of files to process
+} {
+ set new_ids [list]
+ set peeraddr [ad_conn peeraddr]
+
+ # Create the tmp dir if needed
+ set tmp_path [ad_parameter FullTempPhotoDir]
+ if ![file exists $tmp_path] {
+ ns_log Debug "Making: tmp_photo_album_dir_path $tmp_path"
+ ns_mkdir $tmp_path
+ }
+
+ # Fix upload name if missing
+ foreach image_file $image_files {
+
+
+ # Figure out what to call the file...
+ if [empty_string_p $client_name] {
+ set upload_name $image_file
+ } else {
+ set upload_name $client_name
+ }
+ if {![empty_string_p $strip_prefix]} {
+ regsub "^$strip_prefix" $upload_name {} upload_name
+ }
+
+ if ![regexp {([^/\\]+)$} $upload_name match client_filename] {
+ # couldn't find a match
+ set client_filename $upload_name
+ }
+
+ if {[catch {set base_info [pa_file_info $image_file]} errMsg]} {
+ ns_log Warning "Error parsing file data $image_file Error: $errMsg"
+ continue
+ }
+
+ foreach {base_bytes base_width base_height base_type base_mime base_colors base_quantum base_sha256} $base_info { break }
+
+ # If we don't have a mime type we like we try to make a jpg or png
+ #
+ if [empty_string_p $base_mime] {
+ set new_image [file join $tmp_path "tmp-[file rootname [file tail $image_file]]"]
+ if {![empty_string_p $base_colors] && $base_colors < 257} {
+ # convert it to a png
+ if {[catch {exec convert $image_file PNG:$new_image.png} errMsg]} {
+ ns_log Notice "Failed convert to PNG for $image_file (magicktype $base_type)"
+ }
+ if { $remove } {
+ file delete $image_file
+ }
+ set image_file $new_image.png
+ set remove 1
+ } elseif {![empty_string_p $base_colors] && $base_colors > 256} {
+ # convert it to a jpg
+ if {[catch {exec convert $image_file JPG:$new_image.jpg} errMsg]} {
+ ns_log Notice "Failed convert to JPG for $image_file (magicktype $base_type)"
+ }
+ if { $remove } {
+ file delete $image_file
+ }
+ set image_file $new_image.jpg
+ set remove 1
+ } else {
+ ns_log Notice "Is it even an image: $image_file $base_type"
+ }
+
+ # get info again
+ foreach {base_bytes base_width base_height base_type base_mime base_colors base_quantum base_sha256} [pa_file_info $image_file] { break }
+ }
+
+ if {[string equal $base_mime image/jpeg]} {
+ array set exif [pa_get_exif_data ${image_file}]
+ } else {
+ array unset exif
+ }
+
+ set BaseExt [string tolower $base_type]
+
+ if [empty_string_p $base_mime] {
+ ns_log Notice "Photo-Album: Invalid image type $image_file $type even after convert!"
+ continue
+ }
+
+ # Get all the IDs we will need
+ #
+ foreach name [list photo_id photo_rev_id base_item_id base_rev_id thumb_item_id \
+ thumb_rev_id viewer_item_id viewer_rev_id] {
+ set $name [db_nextval "acs_object_id_seq"]
+ }
+
+ # Set the names we use in the content repository.
+ #
+ set image_name "${photo_rev_id}:$client_filename"
+ set base_image_name "base_$client_filename"
+ set vw_image_name "vw_$client_filename"
+ set th_image_name "th_$client_filename"
+
+ # Handle viewer file
+ #
+ set viewer_size [ad_parameter ViewerSize]
+ set viewer_filename [pa_make_file_name -ext $BaseExt $viewer_rev_id]
+ set full_viewer_filename [file join ${tmp_path} ${viewer_filename}]
+ pa_make_new_image $image_file ${full_viewer_filename} $viewer_size
+ foreach {viewer_bytes viewer_width viewer_height viewer_type viewer_mime viewer_colors viewer_quantum viewer_sha256} [pa_file_info $full_viewer_filename] {}
+
+ # Handle thumb file
+ #
+ set thumb_size [ad_parameter ThumbnailSize]
+ set thumb_filename [pa_make_file_name -ext $BaseExt $thumb_rev_id]
+ set full_thumb_filename [file join $tmp_path $thumb_filename]
+ pa_make_new_image ${full_viewer_filename} ${full_thumb_filename} $thumb_size
+ foreach {thumb_bytes thumb_width thumb_height thumb_type thumb_mime thumb_colors thumb_quantum thumb_sha256} [pa_file_info $full_thumb_filename] {}
+
+ # copy the tmp file to the cr's file-system
+ set thumb_filename_relative [cr_create_content_file -move $thumb_item_id $thumb_rev_id ${full_thumb_filename}]
+ set viewer_filename_relative [cr_create_content_file -move $viewer_item_id $viewer_rev_id ${full_viewer_filename}]
+ if { $remove } {
+ set base_filename_relative [cr_create_content_file -move $base_item_id $base_rev_id $image_file]
+ } else {
+ set base_filename_relative [cr_create_content_file $base_item_id $base_rev_id $image_file]
+ }
+
+
+ # Insert the mess into the DB
+ #
+ db_transaction {
+ db_exec_plsql new_photo {
+ declare
+ dummy integer;
+ begin
+
+ dummy := pa_photo.new (
+ name => :image_name,
+ parent_id => :album_id,
+ item_id => :photo_id,
+ revision_id => :photo_rev_id,
+ creation_date => sysdate,
+ creation_user => :user_id,
+ creation_ip => :peeraddr,
+ context_id => :album_id,
+ title => :client_filename,
+ description => :description,
+ is_live => 't',
+ caption => :caption,
+ story => :story,
+ user_filename => :upload_name
+ );
+ end;
+ }
+
+ if {[array size exif] > 1} {
+ foreach {key value} [array get exif] {
+ set tmp_exif_$key $value
+ }
+
+ # Check the datetime looks valid - clock scan works pretty well...
+ if {[catch {clock scan $tmp_exif_DateTime}]} {
+ set tmp_exif_DateTime {}
+ }
+
+ db_dml update_photo_data {
+ UPDATE pa_photos
+ SET camera_model = :tmp_exif_Cameramodel,
+ user_filename = :upload_name,
+ date_taken = datetime(:tmp_exif_DateTime),
+ flash = :tmp_exif_Flashused,
+ aperture = :tmp_exif_Aperture,
+ metering = :tmp_exif_MeteringMode,
+ focal_length = :tmp_exif_Focallength,
+ exposure_time = :tmp_exif_Exposuretime,
+ focus_distance = :tmp_exif_FocusDist,
+ sha256 = :base_sha256
+ WHERE pa_photo_id = :photo_rev_id
+ }
+ }
+
+ pa_insert_image $base_image_name $photo_id $base_item_id $base_rev_id $user_id $peeraddr $photo_id $base_image_name "original image" $base_mime "base" "t" $base_filename_relative $base_height $base_width $base_bytes
+ pa_insert_image $th_image_name $photo_id $thumb_item_id $thumb_rev_id $user_id $peeraddr $photo_id $th_image_name "thumbnail" $thumb_mime "thumb" "t" $thumb_filename_relative $thumb_height $thumb_width $thumb_bytes
+ pa_insert_image $vw_image_name $photo_id $viewer_item_id $viewer_rev_id $user_id $peeraddr $photo_id $vw_image_name "web image" $viewer_mime "viewer" "t" $viewer_filename_relative $viewer_height $viewer_width $viewer_bytes
+
+ pa_grant_privilege_to_creator $photo_id $user_id
+
+ lappend new_ids $photo_id
+ }
+
+ }
+
+ return $new_ids
+}
+
+
+ad_proc -public pa_get_exif_data {
+ file
+} {
+ Returns a array get list with the some of the exif data
+ or an empty string if the file is not a jpg file
+
+ uses jhead
+
+ Keys: Aperture Cameramake Cameramodel CCDWidth DateTime Exposurebias
+ Exposuretime Filedate Filename Filesize Film Flashused Focallength
+ Focallength35 FocusDist Jpegprocess MeteringMode Resolution
+} {
+ # a map from jhead string to internal tags.
+ array set map [list {File date} Filedate \
+ {File name} Filename \
+ {File size} Filesize \
+ {Camera make} Cameramake \
+ {Camera model} Cameramodel \
+ {Date/Time} DateTime \
+ {Resolution} Resolution \
+ {Flash used} Flashused \
+ {Focal length} Focallength \
+ {Focal length35} Focallength35 \
+ {CCD Width} CCDWidth \
+ {Exposure time} Exposuretime \
+ {Aperture} Aperture \
+ {Focus Dist.} FocusDist \
+ {Exposure bias} Exposurebias \
+ {Metering Mode} MeteringMode \
+ {Jpeg process} Jpegprocess \
+ {Film} Film ]
+
+ # try to get the data.
+ if {[catch {set results [exec jhead $file]} errmsg]} {
+ return -code error $errmsg
+ } elseif {[string match {Not JPEG:*} $results]} {
+ return {}
+ }
+
+ # parse data
+ foreach line [split $results "\n"] {
+ regexp {([^:]*):(.*)} $line match tag value
+ set tag [string trim $tag]
+ set value [string trim $value]
+ if {[info exists map($tag)]} {
+ set out($map($tag)) $value
+ }
+ }
+
+ # make sure we have a value for every tag
+ foreach {dummy tag} [array get map] {
+ if {![info exists out($tag)]} {
+ set out($tag) {}
+ }
+ }
+
+ # fix the annoying ones...
+ foreach tag [list Exposuretime FocusDist] {
+ if {[regexp {([0-9.]+)} $out($tag) match new]} {
+ set out($tag) $new
+ }
+ }
+
+ foreach tag [list DateTime Filedate] {
+ regsub {([0-9]+):([0-9][0-9]):} $out($tag) "\\1-\\2-" out($tag)
+ }
+
+ if {[regexp {.*35mm equivalent: ([0-9]+).*} $out(Focallength) match new]} {
+ set out(Focallength35) $new
+ } else {
+ set out(Focallength35) {}
+ }
+ regsub {([0-9.]+)mm.*} $out(Focallength) "\\1" out(Focallength)
+
+ if {[string equal -nocase $out(Flashused) yes]} {
+ set out(Flashused) 1
+ } else {
+ set out(Flashused) 0
+ }
+
+ if {![empty_string_p $out(Cameramake)]} {
+ set out(Film) Digital
+ }
+
+ regsub {([0-9]+).*} $out(Filesize) "\\1" out(Filesize)
+
+ return [array get out]
+}
+
+
+ad_proc -public pa_clipboards_multirow {
+ -create_new:boolean
+ -force_default:boolean
+ user_id
+ datasource
+} {
+ creates a multirow datasource with the existing clipboards
+
+ @param create_new add a "Create new folder" entry to list
+ @param force_default create the datasource with a default folder even if none exist
+ @param user_id the owner id for the folders
+ @param the datasource name to use.
+
+ @author Jeff Davis davis@xarg.net
+ @creation-date 2002-10-30
+} {
+
+ db_multirow $datasource clipboards {select collection_id, title, 0 as selected from pa_collections where owner_id = :user_id}
+
+ if {[template::multirow size $datasource] > 0} {
+ if {$create_new_p} {
+ template::multirow append $datasource -1 "Create a new clipboard" 0
+ }
+
+ } else {
+ if { $force_default_p } {
+ template::multirow create $datasource collection_id title selected
+ template::multirow append $datasource 0 "General" 0
+ }
+ }
+ return [template::multirow size $datasource]
+}
+
Index: openacs-4/packages/photo-album/tcl/photo-album-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/tcl/photo-album-procs.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/tcl/photo-album-procs.xql 10 Jun 2003 10:06:42 -0000 1.1
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ select description from cr_folders where folder_id = :folder_id
+
+
+
+
+
+ select
+ ci.item_id
+from cr_items ci,
+ cr_child_rels ccr
+where ci.live_revision is not null
+ and ci.content_type = 'pa_photo'
+ and ccr.parent_id = :album_id
+ and ci.item_id = ccr.child_id
+order by ccr.order_n
+
+
+
+
+
+
+
+ select
+ ceil(count(*) / [ad_parameter ThumbnailsPerPage])
+ from
+ ($sql)
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-add-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-add-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-add-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,28 @@
+
+
+
+ oracle8.1.6
+
+
+
+
+ begin
+ :1 := pa_album.new (
+ name => :name,
+ album_id => :album_id,
+ parent_id => :parent_id,
+ is_live => 't',
+ creation_user => :user_id,
+ creation_ip => :peeraddr,
+ title => :title,
+ description => :description,
+ story => :story
+ photographer => :photographer
+ );
+ end;
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-add-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-add-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-add-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,30 @@
+
+
+
+ postgresql7.1
+
+
+
+ select pa_album__new (
+ :name, -- name
+ :album_id, -- album_id
+ :parent_id, -- parent_id
+ 't', -- is_live
+ :user_id, -- creation_user
+ :peeraddr, -- creation_ip
+ :title, -- title
+ :description, -- description
+ :story, -- story
+ :photographer, -- photographer
+ null, -- revision_id
+ current_timestamp, -- creation_date
+ null, -- locale
+ null, -- context_id
+ current_timestamp, -- publish_date
+ null -- nls_language
+ );
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-add.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-add.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-add.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+Create a New Album
+@context_list@
+
+
Index: openacs-4/packages/photo-album/www/album-add.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-add.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-add.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,98 @@
+# /packages/photo-album/www/album-add.tcl
+
+ad_page_contract {
+
+ Add a album to an existing folder
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/8/2000
+ @cvs-id $Id: album-add.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ parent_id:integer,notnull
+} -validate {
+ valid_parent_folder -requires {parent_id:integer} {
+ if [string equal [pa_is_folder_p $parent_id] "f"] {
+ ad_complain "The specified parent folder is not valid."
+ }
+ }
+} -properties {
+ context_list:onevalue
+}
+
+ad_require_permission $parent_id "pa_create_album"
+
+set context_list [pa_context_bar_list -final "Create a New Album" $parent_id]
+
+template::form create album_add
+
+template::element create album_add album_id -label "album ID" \
+ -datatype integer -widget hidden
+
+template::element create album_add parent_id -label "Parent ID" \
+ -datatype integer -widget hidden
+
+template::element create album_add title -html { size 30 } \
+ -label "Album Name" -datatype text
+
+template::element create album_add photographer -html { size 50} \
+ -label "Photographer" -datatype text -optional
+
+template::element create album_add description -html { size 50 } \
+ -label "Album Description" -datatype text -optional
+
+template::element create album_add story -html {cols 50 rows 4 wrap soft} \
+ -label "Album Story" -datatype text -widget textarea -optional
+
+if { [template::form is_request album_add] } {
+ set album_id [db_nextval acs_object_id_seq]
+ template::element set_properties album_add album_id -value $album_id
+ template::element set_properties album_add parent_id -value $parent_id
+}
+
+if { [template::form is_valid album_add] } {
+ # vaild new album submission so create new album
+ set user_id [ad_conn user_id]
+ set peeraddr [ad_conn peeraddr]
+ set album_id [template::element::get_value album_add album_id]
+ set parent_id [template::element::get_value album_add parent_id]
+ set title [template::element::get_value album_add title]
+ set description [template::element::get_value album_add description]
+ set story [template::element::get_value album_add story]
+ set photographer [template::element::get_value album_add photographer]
+ # file safe title into name
+ regsub -all { +} [string tolower $title] {_} name
+ regsub -all {/+} $name {-} name
+
+ db_transaction {
+ # add the album
+ db_exec_plsql new_album {}
+
+ pa_grant_privilege_to_creator $album_id $user_id
+
+ } on_error {
+ # most likely a duplicate name or a double click
+
+ if [db_string duplicate_check "
+ select count(*)
+ from cr_items
+ where (item_id = :album_id or name = :name)
+ and parent_id = :parent_id"] {
+ ad_return_complaint 1 "Either there is already an album with the name \"$name\"
+ or you clicked on the button more than once. You can
+ return to the directory listing to see if your album is there."
+ } else {
+ ad_return_complaint 1 "We got an error that we couldn't readily identify. Please let the system owner know about this.
+
+
$errmsg
"
+ }
+
+ ad_script_abort
+ }
+ #redirect back to index page with parent_id
+
+ ad_returnredirect "?folder_id=$parent_id"
+
+ ad_script_abort
+}
+
+ad_return_template
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/album-add.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-add.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-add.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ select count(*)
+ from cr_items
+ where (item_id = :album_id or name = :name)
+ and parent_id = :parent_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-delete-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-delete-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-delete-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,24 @@
+
+
+
+ oracle8.1.6
+
+
+
+
+ begin
+ pa_album.delete(:album_id);
+ end;
+
+
+
+
+
+
+
+ select content_item.get_title(:album_id,'t') from dual
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-delete-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-delete-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-delete-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,20 @@
+
+
+
+ postgresql7.1
+
+
+
+ select pa_album__delete(:album_id)
+
+
+
+
+
+
+ select content_item__get_title(:album_id,'t')
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-delete.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-delete.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-delete.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,16 @@
+
+@title@
+@context_list@
+
+
Index: openacs-4/packages/photo-album/www/album-delete.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-delete.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-delete.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,58 @@
+# /packages/photo-album/www/album-delete.tcl
+
+ad_page_contract {
+ page to confirm and delete album.
+ album must be empty to delete
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 1/8/2000
+ @cvs-id $Id: album-delete.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+ {confirmed_p "f"}
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+
+ no_children -requires {album_id:integer} {
+ if { [pa_count_photos_in_album $album_id] > 0 } {
+ ad_complain "We're sorry, but you cannot delete albums unless they are already empty."
+ }
+ }
+} -properties {
+ album_id:onevalue
+ title:onevalue
+ context_bar:onevalue
+}
+
+# to delete a album must have delete permission on the album
+# and write on parent folder
+set parent_folder_id [db_string get_parent "select parent_id from cr_items where item_id = :album_id"]
+ad_require_permission $album_id delete
+ad_require_permission $parent_folder_id write
+
+if { [string equal $confirmed_p "t"] } {
+ # they have confirmed that they want to delete the album
+
+ db_exec_plsql album_delete "
+ begin
+ pa_album.delete(:album_id);
+ end;"
+
+ pa_flush_photo_in_album_cache $album_id
+
+ ad_returnredirect "?folder_id=$parent_folder_id"
+ ad_script_abort
+
+} else {
+ # they still need to confirm
+
+ set title [db_string album_name "
+ select content_item.get_title(:album_id,'t') from dual"]
+
+ set context_list [pa_context_bar_list -final "Delete Album" $album_id]
+
+}
Index: openacs-4/packages/photo-album/www/album-delete.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-delete.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-delete.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,11 @@
+
+
+
+
+
+ select parent_id from cr_items where item_id = :album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-edit-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-edit-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-edit-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,37 @@
+
+
+
+ oracle8.1.6
+
+
+
+
+ declare
+ dummy integer;
+ begin
+
+ dummy := content_revision.new (
+ title => :new_title,
+ description => :new_desc,
+ item_id => :album_id,
+ revision_id => :revision_id,
+ creation_date => sysdate,
+ creation_user => :user_id,
+ creation_ip => :peeraddr
+ );
+ end;
+
+
+
+
+
+
+ begin
+ content_item.set_live_revision (
+ revision_id => :revision_id
+ );
+ end;
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-edit-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-edit-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-edit-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,34 @@
+
+
+
+ postgresql7.1
+
+
+
+ select content_revision__new (
+ :new_title, -- title
+ :new_desc, -- description
+ current_timestamp, -- publish_date
+ null, -- mime_type
+ null, -- nls_language
+ null, -- text
+ :album_id, -- item_id
+ :revision_id, -- revision_id
+ current_timestamp, -- creation_date
+ :user_id, -- creation_user
+ :peeraddr -- creation_ip
+ )
+
+
+
+
+
+ select content_item__set_live_revision (
+ :revision_id, -- revision_id
+ 'ready' -- publish_status
+ )
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-edit.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-edit.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-edit.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+@title@
+@context_list@
+
Edit the Album:
+
Index: openacs-4/packages/photo-album/www/album-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-edit.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-edit.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,98 @@
+# /packages/photo-album/www/album-edit.tcl
+
+ad_page_contract {
+
+ Edit Photo Properties
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/11/2000
+ @cvs-id $Id: album-edit.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+} -properties {
+ context_list:onevalue
+}
+
+ad_require_permission $album_id "write"
+
+set user_id [ad_conn user_id]
+set context_list [pa_context_bar_list -final "Edit Album Attributes" $album_id]
+
+template::form create edit_album
+
+template::element create edit_album album_id -label "album ID" \
+ -datatype integer -widget hidden
+
+template::element create edit_album revision_id -label "revision ID" \
+ -datatype integer -widget hidden
+
+template::element create edit_album previous_revision -label "previous_revision" \
+ -datatype integer -widget hidden
+
+template::element create edit_album iconic -label "Iconic" \
+ -datatype integer -widget hidden -optional
+
+template::element create edit_album title -html { size 30 } \
+ -label "Album Name" -datatype text
+
+template::element create edit_album photographer -html { size 50} \
+ -label "Photographer" -datatype text -optional
+
+template::element create edit_album description -html { size 50} \
+ -label "Album Description" -datatype text -optional
+
+template::element create edit_album story -html { cols 50 rows 4 wrap soft } \
+ -label "Album Story" -datatype text -widget textarea -optional
+
+
+# this needs to be outside of the s_request block so title attribute
+# is defined during a form error
+
+db_1row get_album_info {}
+
+if { [template::form is_request edit_album] } {
+ set revision_id [db_nextval acs_object_id_seq]
+ template::element set_properties edit_album revision_id -value $revision_id
+ template::element set_properties edit_album album_id -value $album_id
+ template::element set_properties edit_album previous_revision -value $previous_revision
+ template::element set_properties edit_album title -value $title
+ template::element set_properties edit_album description -value $description
+ template::element set_properties edit_album story -value $story
+ template::element set_properties edit_album iconic -value $iconic
+ template::element set_properties edit_album photographer -value $photographer
+}
+
+if { [template::form is_valid edit_album] } {
+ set album_id [template::element::get_value edit_album album_id]
+ set revision_id [template::element::get_value edit_album revision_id]
+ set new_title [template::element::get_value edit_album title]
+ set new_desc [template::element::get_value edit_album description]
+ set new_story [template::element::get_value edit_album story]
+ set iconic [template::element::get_value edit_album iconic]
+ set new_photographer [template::element::get_value edit_album photographer]
+ set previous_revision [template::element::get_value edit_album previous_revision]
+ set peeraddr [ad_conn peeraddr]
+
+ db_transaction {
+ db_exec_plsql update_album_attributes {}
+
+ db_dml insert_pa_albums {}
+
+ db_exec_plsql set_live_album {}
+ } on_error {
+ ad_return_complaint 1 "An error occurred while processing your input. Please let the system owner know about this.
+
$errmsg
"
+
+ ad_script_abort
+ }
+ ad_returnredirect "album?album_id=$album_id"
+ ad_script_abort
+}
+
+ad_return_template
Index: openacs-4/packages/photo-album/www/album-edit.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-edit.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-edit.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+ select
+ cr.title,
+ cr. description,
+ pa.story,
+ pa.iconic as iconic,
+ pa.photographer,
+ ci.live_revision as previous_revision
+ from cr_items ci,
+ cr_revisions cr,
+ pa_albums pa
+ where ci.live_revision = cr.revision_id
+ and cr.revision_id = pa.pa_album_id
+ and ci.item_id = :album_id
+
+
+
+
+
+
+ insert into pa_albums (pa_album_id, story, iconic, photographer)
+ values
+ (:revision_id, :new_story, :iconic, :new_photographer)
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-move-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-move-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-move-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,44 @@
+
+
+
+ oracle8.1.6
+
+
+
+ select title, description, story from pa_albumsx where object_id = content_item.get_live_revision(:album_id)
+
+
+
+
+
+
+ select
+ lpad (' ',((level - 1) * 6),' ') || content_folder.get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci
+ where ci.content_type = 'content_folder'
+ -- do not include the albums current folder in move to list
+ and ci.item_id != :old_folder_id
+ and acs_permission.permission_p(ci.item_id, :user_id, 'pa_create_album') = 't'
+ connect by prior ci.item_id = ci.parent_id
+ start with ci.item_id = :root_folder_id
+
+
+
+
+
+
+
+
+ begin
+ content_item.move (
+ item_id => :album_id,
+ target_folder_id => :new_folder_id
+ );
+ end;
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-move-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-move-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-move-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,40 @@
+
+
+
+ postgresql7.1
+
+
+
+ select title, description, story from pa_albumsx where object_id = content_item__get_live_revision(:album_id)
+
+
+
+
+
+
+ select
+ repeat(' ',(tree_level(ci.tree_sortkey) - tree_level(i2.tree_sortkey) - 1) * 6) || content_folder__get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci, cr_items i2
+ where ci.content_type = 'content_folder'
+ -- do not include the albums current folder in move to list
+ and ci.item_id <> :old_folder_id
+ and acs_permission__permission_p(ci.item_id, :user_id, 'pa_create_album')
+ and ci.tree_sortkey between i2.tree_sortkey and tree_right(i2.tree_sortkey)
+ and i2.item_id = :root_folder_id
+ order by ci.tree_sortkey
+
+
+
+
+
+
+ select content_item__move (
+ :album_id, -- item_id
+ :new_folder_id -- target_folder_id
+ )
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/album-move.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-move.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-move.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+@title@
+@context_list@
+
Move Album to new folder:
+
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/album-move.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-move.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album-move.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,114 @@
+# /packages/photo-album/www/album-move.tcl
+
+ad_page_contract {
+ Allows user to move an album from one album to another folder in the same package instance
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 1/8/2000
+ @cvs-id $Id: album-move.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+}
+set context_list [pa_context_bar_list -final "Move Album" $album_id]
+set user_id [ad_conn user_id]
+
+# to move an album need write on album, and old parent folder
+# and pa_create_album on new parent folder (which is check in the is_valid block)
+
+set old_folder_id [db_string get_parent_folder "select parent_id from cr_items where item_id = :album_id"]
+ad_require_permission $album_id write
+ad_require_permission $old_folder_id write
+
+db_1row get_album_info {select title, description, story from pa_albumsx where object_id = content_item.get_live_revision(:album_id)}
+
+# build form
+
+template::form create move_album
+
+template::element create move_album album_id -label "album ID" \
+ -datatype integer -widget hidden
+
+
+# options query retreive all folders in package that user can add an album to
+set root_folder_id [pa_get_root_folder]
+
+template::element create move_album new_folder_id -label "Choose New Folder for Album" \
+ -datatype integer -widget select \
+ -options [db_list_of_lists get_folders "select
+ lpad (' ',((level - 1) * 18),' ') || content_folder.get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci
+ where ci.content_type = 'content_folder'
+ -- do not include the albums current folder in move to list
+ and ci.item_id != :old_folder_id
+ and acs_permission.permission_p(ci.item_id, :user_id, 'pa_create_album') = 't'
+ connect by prior ci.item_id = ci.parent_id
+ start with ci.item_id = :root_folder_id
+ "]
+
+if { [template::form is_request move_album] } {
+ template::element set_properties move_album album_id -value $album_id
+}
+
+if { [template::form is_valid move_album] } {
+ set new_folder_id [template::element::get_value move_album new_folder_id]
+
+ ad_require_permission $new_folder_id "pa_create_album"
+
+ if [string equal [pa_is_folder_p $new_folder_id] "f"] {
+ # may add some sort of error message
+ # but this case only happens due to url hacking
+ # (or coding errors, which never happen)
+ ad_script_abort
+ }
+
+ db_transaction {
+
+ db_exec_plsql album_move "
+ begin
+ content_item.move (
+ item_id => :album_id,
+ target_folder_id => :new_folder_id
+ );
+ end;
+ "
+
+ db_dml context_update "
+ update acs_objects
+ set context_id = :new_folder_id
+ where object_id = :album_id
+ "
+
+ } on_error {
+ # most likely a duplicate name or a double click
+
+ set folder_name [db_string folder_name "
+ select name from cr_items where item_id = :album_id"]
+
+ if [db_string duplicate_check "
+ select count(*)
+ from cr_items
+ where name = :folder_name
+ and parent_id = :new_folder_id"] {
+ ad_return_complaint 1 "Either there is already an album in the specified folder with the name \"$folder_name\" or you clicked on the button more than once. You can return to the new folder to see if your album is there."
+ } else {
+ ad_return_complaint 1 "We got an error that we couldn't readily identify. Please let the system owner know about this.
+
+
Click on the small photos to see a bigger
+version, the numbers to see different pages, or the Next or Previous
+page links to move back and forth. You can also pick photos for
+printing or emailing on the individual photo display page.
+
+
Index: openacs-4/packages/photo-album/www/album.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,122 @@
+# /packages/photo-album/www/album.tcl
+ad_page_contract {
+ Album display page.
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @author Jeff Davis (davis@xarg.net)
+
+ @creation-date 12/10/2000
+ @cvs-id $Id: album.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+ {page:integer,notnull "1"}
+ {msg:integer,notnull "0"}
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+} -properties {
+ album_id:onevalue
+ title:onevalue
+ description:onevalue
+ story:onevalue
+ context:onevalue
+ child_photo:multirow
+ page_nav:onevalue
+ admin_p:onevalue
+ photo_p:onevalue
+ write_p:onevalue
+ move_p:onevalue
+ delete_p:onevalue
+ collections:onevalue
+}
+
+set user_id [ad_conn user_id]
+
+# check for read permission on album
+ad_require_permission $album_id read
+
+set context [pa_context_bar_list $album_id]
+
+db_1row get_album_info {}
+
+# to move an album need write on album and write on parent folder
+set move_p [expr $write_p && $folder_write_p]
+
+# to delete an album, album must be empty, need delete on album, and write on parent folder
+set has_children_p [expr [pa_count_photos_in_album $album_id] > 0]
+set delete_p [expr !($has_children_p) && $album_delete_p && $folder_write_p]
+
+# Did we get a msg id, if so display it at the top of the page
+# TODO: JCD: We should remove it from vars so it does not propigate
+array set msgtext {
+ 1 {Your text changes have been saved and any image changes such as rotations
+ are being carried out in the background}
+ 2 {There was a problem with your update. Please notify the webmaster}
+}
+
+if {$msg && [info exists msgtext($msg)]} {
+ set message $msgtext($msg)
+} else {
+ set message {}
+}
+
+# change design so permission checks stop at the album level
+# load testing showed serious performance problems when
+# each photo could have individual permissions
+#
+# for now all photo in an album inherit the permission of the album that
+# contains them. Only need to check the read permission of the album, which was done at the top of the page.
+
+set photos_on_page [pa_all_photos_on_page $album_id $page]
+
+if {$has_children_p && [llength $photos_on_page] > 0} {
+ # query gets all child photos in album
+ # I query the data without an orderby in the sql to cut the querry time
+ # and then sort the returned data manually while constructing the multirow datasource.
+ # This goes against the theory of let oracle do the hard work, but load testing and
+ # query tuning showed that the order by doubled the query time while sorting a few rows in tcl was fast
+
+ # wtem@olywa.net, 2001-09-24
+ db_foreach get_child_photos {} {
+ set val(photo_id) $photo_id
+ set val(caption) $caption
+ set val(thumb_path) $thumb_path
+ set val(thumb_height) $thumb_height
+ set val(thumb_width) $thumb_width
+ set child($photo_id) [array get val]
+ }
+
+ # if the structure of the multirow datasource ever changes, this needs to be rewritten
+ set counter 0
+ foreach id $photos_on_page {
+ if {[info exists child($id)]} {
+ incr counter
+ foreach {key value} $child($id) {
+ set child_photo:${counter}($key) $value
+ }
+ }
+ }
+ set child_photo:rowcount $counter
+
+ set pages [list]
+ set total_pages [pa_count_pages_in_album $album_id]
+
+ for {set i 1} {$i <= $total_pages} {incr i} {
+ lappend pages $i
+ }
+ set page_nav [pa_pagination_bar $page $pages "album?[export_vars -url {album_id}]&page=" page]
+
+} else {
+ # don't bother querying for children if we know they don't exist
+ set child_photo:rowcount 0
+ set page_nav ""
+}
+
+set collections [db_string collections {select count(*) from pa_collections where owner_id = :user_id}]
+
+ad_return_template
+
+
Index: openacs-4/packages/photo-album/www/album.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/album.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+ select ci.item_id as photo_id,
+ (select pp.caption from pa_photos pp where pp.pa_photo_id = ci.live_revision) as caption,
+ i.image_id as thumb_path,
+ i.height as thumb_height,
+ i.width as thumb_width
+ from cr_items ci,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+ where ccr2.relation_tag = 'thumb'
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ci2.live_revision = i.image_id
+ and ci.live_revision is not null
+ and ci.item_id in ([join $photos_on_page ","])
+
+
+
+
+
+select cr.title,
+ cr.description,
+ pa.story,
+ ci.parent_id as parent_folder_id,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'admin') = 't' then 1 else 0 end as admin_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'pa_create_photo') = 't' then 1 else 0 end as photo_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'write') ='t' then 1 else 0 end as write_p,
+ case when acs_permission__permission_p(ci.parent_id, :user_id, 'write') = 't' then 1 else 0 end as folder_write_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'delete') = 't' then 1 else 0 end as album_delete_p
+from cr_items ci,
+ cr_revisions cr,
+ pa_albums pa
+where ci.live_revision = cr.revision_id
+ and ci.live_revision = pa_album_id
+ and ci.item_id = :album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/base-photo.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/base-photo.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/base-photo.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,20 @@
+
+@title@
+@context@
+1
+
+@photo_nav_html@
+
Index: openacs-4/packages/photo-album/www/base-photo.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/base-photo.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/base-photo.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,72 @@
+# /packages/photo-album/www/photo.tcl
+
+ad_page_contract {
+
+ Display page for base sized image.
+ Only accessable if parameter set for package
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 2/1/2000
+ @cvs-id $Id: base-photo.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ photo_id:integer,notnull
+} -validate {
+ valid_photo -requires {photo_id:integer} {
+ if [string equal [pa_is_photo_p $photo_id] "f"] {
+ ad_complain "The specified photo is not valid."
+ }
+ }
+} -properties {
+ context:onevalue
+ title:onevalue
+ description:onevalue
+ story:onevalue
+ caption:onevalue
+ path:onevalue
+ height:onevalue
+ width:onevalue
+}
+
+if {![string equal [ad_parameter AllowBasePhotoAccessP] "t"]} {
+ ad_return_forbidden "No Access" "The Administrator of this sub-site has restricted access base photos."
+ ad_script_abort
+}
+
+ad_require_permission $photo_id "read"
+
+set user_id [ad_conn user_id]
+set context [pa_context_bar_list -final "Full Size Image" $photo_id]
+
+# query all the photo and permission info with a single trip to database
+db_1row get_photo_info {select
+ pp.caption,
+ pp.story,
+ cr.title,
+ cr.description,
+ i.height as height,
+ i.width as width,
+ i.image_id as image_id,
+ ci.parent_id as album_id
+from cr_items ci,
+ cr_revisions cr,
+ pa_photos pp,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+where cr.revision_id = pp.pa_photo_id
+ and ci.live_revision = cr.revision_id
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ccr2.relation_tag = 'base'
+ and ci2.live_revision = i.image_id
+ and ci.item_id = :photo_id
+}
+set path $image_id
+
+# determine what album page the photo is on so page can present link back to thumbnail page
+set page_num [pa_page_of_photo_in_album $photo_id $album_id]
+
+set photo_nav_html [pa_pagination_bar $photo_id [pa_all_photos_in_album $album_id] "base-photo?photo_id="]
+
+ad_return_template
+
Index: openacs-4/packages/photo-album/www/base-photo.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/base-photo.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/base-photo.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,33 @@
+
+
+
+
+
+ select
+ pp.caption,
+ pp.story,
+ cr.title,
+ cr.description,
+ i.height as height,
+ i.width as width,
+ i.image_id as image_id,
+ ci.parent_id as album_id
+from cr_items ci,
+ cr_revisions cr,
+ pa_photos pp,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+where cr.revision_id = pp.pa_photo_id
+ and ci.live_revision = cr.revision_id
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ccr2.relation_tag = 'base'
+ and ci2.live_revision = i.image_id
+ and ci.item_id = :photo_id
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/clipboard-ae.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-ae.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/clipboard-ae.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+Photo clipboard
+"clipboard add/edit"
+
+
Index: openacs-4/packages/photo-album/www/clipboard-ae.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-ae.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/clipboard-ae.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,46 @@
+# /packages/photo-album/www/clipboard-ae.tcl
+ad_page_contract {
+ add/edit a photo clipboard.
+
+ If a photo_id provided, it is attached after the add/edit finishes.
+
+ @author Jeff Davis davis@xarg.net
+ @creation-date 10/30/2002
+ @cvs-id $Id: clipboard-ae.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ collection_id:optional
+ {photo_id:integer,optional {}}
+}
+
+set user_id [ad_conn user_id]
+set peeraddr [ad_conn peeraddr]
+set context [ad_conn package_id]
+
+ad_form -name clip_ae -export {photo_id} -form {
+ collection_id:key(acs_object_id_seq)
+
+ {title:text(text) {label "Clipboard name"}
+ {html {size 60}}}
+} -select_query {
+ select title from pa_collections where collection_id = :collection_id
+} -validate {
+ {title
+ {![string is space $title]}
+ "You must provide a non-empty name for the clipboard"
+ }
+} -new_data {
+ db_0or1row new_collection {select pa_collection__new(:collection_id, :user_id, :title, now(), :user_id, :peeraddr, :context);}
+} -edit_data {
+ db_dml do_update "
+ update pa_collections
+ set title = :title
+ where collection_id = :collection_id"
+} -after_submit {
+ if {![empty_string_p $photo_id]} {
+ ad_returnredirect "clipboard-attach?photo_id=$photo_id&collection_id=$collection_id"
+ } else {
+ ad_returnredirect "clipboards"
+ }
+ ad_script_abort
+}
+
Index: openacs-4/packages/photo-album/www/clipboard-attach.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-attach.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/clipboard-attach.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,49 @@
+# /packages/photo-album/www/clipboard-attach.tcl
+ad_page_contract {
+
+ Add a photo to one of your clipboards (or create a new one if either
+ asked for or none exist). Requires registration.
+
+ @author Jeff Davis davis@xarg.net
+ @creation-date 10/30/2002
+ @cvs-id $Id: clipboard-attach.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ photo_id:integer,notnull
+ collection_id:integer,notnull
+}
+
+ad_maybe_redirect_for_registration
+
+set user_id [ad_conn user_id]
+set peeraddr [ad_conn peeraddr]
+set context [ad_conn package_id]
+
+if {$collection_id < 0} {
+ ad_returnredirect "clipboard-ae?photo_id=$photo_id"
+ ad_script_abort
+}
+
+# If we got collection_id 0 then we need to create a "General" clipboard
+if {$collection_id == 0} {
+ set title "General"
+
+ set collection_id [db_nextval acs_object_id_seq]
+
+ if {[catch {db_1row new_collection {select pa_collection__new(:collection_id, :user_id, :title, now(), :user_id, :peeraddr, :context)}} errMsg]} {
+ ad_return_error "Clipboard Insert error" "Error putting photo into clipboard
$errMsg
"
+ }
+}
+
+if {$collection_id > 0} {
+ if {[catch {db_dml map_photo {insert into pa_collection_photo_map (collection_id, photo_id) select :collection_id, :photo_id where
+ acs_permission__permission_p(:collection_id, :user_id, 'write') = 't'}} errMsg]} {
+ # Check if it was a pk violation (i.e. already inserted)
+ # JCD: should check if this works for oracle. Might have case problem.
+ if {![string match "*pa_collection_photo_map_pk*" $errMsg]} {
+ ad_return_error "Clipboard Insert error" "Error putting photo into clipboard
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/clipboard-view.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-view.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/clipboard-view.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,44 @@
+ad_page_contract {
+ display the images in a given clipboard
+
+ @author Jeff Davis (davis@xarg.net)
+ @creation-date 2002-10-30
+ @cvs-id $Id: clipboard-view.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ collection_id:integer,notnull
+} -properties {
+ context:onevalue
+ title:onevalue
+ owner_id:onevalue
+ owner_name:onevalue
+ user_id:onevalue
+ base_url:onevalue
+ images:multirow
+}
+
+set user_id [ad_conn user_id]
+
+if {![db_0or1row collection {select first_names || ' ' || last_name as owner_name, owner_id, title from pa_collections, cc_users where collection_id = :collection_id and owner_id = user_id}] } {
+ ad_return_complaint 1 "
invalid clipboard"
+ ad_script_abort
+}
+
+# Check that the user is permissioned for this collection.
+permission::require_permission -party_id $user_id -object_id $collection_id -privilege read
+
+set context [list [list clipboards clipboards] $title]
+
+db_multirow images get_images {
+ select m.photo_id, p.image_id, p.height, p.width, p.caption, to_char(p.date_taken, 'Mon FMDD, YYYY') as taken, f.width as base_width, f.image_id as base_id, f.height as base_height
+ from pa_collection_photo_map m,
+ all_photo_images p,
+ all_photo_images f
+ where collection_id = :collection_id
+ and p.item_id = m.photo_id
+ and p.relation_tag = 'thumb'
+ and f.item_id = m.photo_id
+ and f.relation_tag = 'base'
+}
+
+set returnurl "[ad_url][ad_conn package_url]"
+set base_url "[ad_url][ad_conn package_url]images/"
Index: openacs-4/packages/photo-album/www/clipboards.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboards.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/clipboards.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,25 @@
+
+ Your clipboards
+ clipboards
+
+ You will have to log in or
+ register
+ in order to manage clipboards.
+
+
+
+ You do not currently have any clipboards defined. You will
+ need to browse the photos and add them to a clipboard to use
+ this part of the site.
+
+
+
"
+
+ ad_script_abort
+ }
+ #redirect back to index page with parent_id
+
+ ad_returnredirect "?folder_id=$folder_id"
+
+ ad_script_abort
+}
+
+ad_return_template
Index: openacs-4/packages/photo-album/www/folder-move-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-move-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/folder-move-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,45 @@
+
+
+
+ oracle8.1.6
+
+
+
+ select content_folder.get_label(:folder_id) as title from dual
+
+
+
+
+
+
+ select padded_name, folder_id from (select
+ ci.item_id,
+ lpad (' ',((level - 1) * 6),' ') || content_folder.get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci
+ where ci.content_type = 'content_folder'
+ start with ci.item_id = :root_folder_id
+ connect by prior ci.item_id = ci.parent_id
+ and ci.item_id != :folder_id
+ )
+ where acs_permission.permission_p(item_id, :user_id, 'pa_create_folder') = 't'
+
+
+
+
+
+
+
+
+ begin
+ content_folder.move (
+ folder_id => :folder_id,
+ target_folder_id => :new_folder_id
+ );
+ end;
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/folder-move-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-move-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/folder-move-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,42 @@
+
+
+
+ postgresql7.1
+
+
+
+ select content_folder__get_label(:folder_id) as title
+
+
+
+
+
+
+ select
+ repeat(' ',(tree_level(ci.tree_sortkey) - tree_level(i2.tree_sortkey) - 1) * 6) || content_folder__get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci, cr_items i2
+ where ci.content_type = 'content_folder'
+ and ci.item_id <> :folder_id
+ and ci.tree_sortkey between i2.tree_sortkey and tree_right(i2.tree_sortkey)
+ and i2.item_id = :root_folder_id
+ and acs_permission__permission_p(ci.item_id, :user_id, 'pa_create_folder') = 't'
+ order by ci.tree_sortkey
+
+
+
+
+
+
+
+
+ select content_folder__move (
+ :folder_id, -- folder_id
+ :new_folder_id -- target_folder_id
+ )
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/folder-move.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-move.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/folder-move.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+@title@
+@context_list@
+
Move folder to new older:
+
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/folder-move.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-move.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/folder-move.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,122 @@
+# /packages/photo-album/www/folder-move.tcl
+
+ad_page_contract {
+ Allows user to move an folder from one folder to another folder in the same package instance
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 1/8/2000
+ @cvs-id $Id: folder-move.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ folder_id:integer,notnull
+} -validate {
+ valid_folder -requires {folder_id:integer} {
+ if [string equal [pa_is_folder_p $folder_id] "f"] {
+ ad_complain "The specified folder is not valid."
+ }
+ }
+
+ not_root_folder -requires {folder_id} {
+ if { $folder_id == [pa_get_root_folder] } {
+ ad_complain "You may not move the root folder."
+ }
+ }
+}
+
+set context_list [pa_context_bar_list -final "Move Folder" $folder_id]
+set user_id [ad_conn user_id]
+
+# to move an folder need write on folder, and old parent folder
+# and pa_create_folder on new parent folder (which is check in the is_valid block)
+
+set old_folder_id [db_string get_parent_folder "select parent_id from cr_items where item_id = :folder_id"]
+ad_require_permission $folder_id write
+ad_require_permission $old_folder_id write
+
+db_1row get_folder_info {select content_folder.get_label(:folder_id) as title from dual}
+
+# build form
+
+template::form create move_folder
+
+template::element create move_folder folder_id -label "folder ID" \
+ -datatype integer -widget hidden
+
+
+# options query retreive all folders in package that user can add an folder to
+set root_folder_id [pa_get_root_folder]
+
+template::element create move_folder new_folder_id -label "Choose New Folder for Folder" \
+ -datatype integer -widget select \
+ -options [db_list_of_lists get_folders "select padded_name, folder_id from (select
+ ci.item_id,
+ lpad (' ',((level - 1) * 18),' ') || content_folder.get_label(ci.item_id) as padded_name,
+ ci.item_id as folder_id
+ from cr_items ci
+ where ci.content_type = 'content_folder'
+ start with ci.item_id = :root_folder_id
+ connect by prior ci.item_id = ci.parent_id
+ and ci.item_id != :folder_id
+ )
+ where acs_permission.permission_p(item_id, :user_id, 'pa_create_folder') = 't'
+ "]
+
+if { [template::form is_request move_folder] } {
+ template::element set_properties move_folder folder_id -value $folder_id
+}
+
+if { [template::form is_valid move_folder] } {
+ set new_folder_id [template::element::get_value move_folder new_folder_id]
+
+ ad_require_permission $new_folder_id "pa_create_folder"
+
+ if [string equal [pa_is_folder_p $new_folder_id] "f"] {
+ # may add some sort of error message
+ # but this case only happens due to url hacking
+ # (or coding errors, which never happen)
+ ad_script_abort
+ }
+
+ db_transaction {
+
+ db_exec_plsql folder_move "
+ begin
+ content_folder.move (
+ folder_id => :folder_id,
+ target_folder_id => :new_folder_id
+ );
+ end;
+ "
+
+ db_dml context_update "
+ update acs_objects
+ set context_id = :new_folder_id
+ where object_id = :folder_id
+ "
+
+ } on_error {
+ # most likely a duplicate name or a double click
+
+ set folder_name [db_string folder_name "
+ select name from cr_items where item_id = :folder_id"]
+
+ if [db_string duplicate_check "
+ select count(*)
+ from cr_items
+ where name = :folder_name
+ and parent_id = :new_folder_id"] {
+ ad_return_complaint 1 "Either there is already an folder in the specified folder with the name \"$folder_name\" or you clicked on the button more than once. You can return to the new folder to see if your folder is there."
+ } else {
+ ad_return_complaint 1 "We got an error that we couldn't readily identify. Please let the system owner know about this.
+
+
$errmsg
"
+ }
+
+ ad_script_abort
+ }
+
+ ad_returnredirect "?folder_id=$new_folder_id"
+ ad_script_abort
+}
+
+ad_return_template
+
Index: openacs-4/packages/photo-album/www/folder-move.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-move.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/folder-move.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,41 @@
+
+
+
+
+
+ select parent_id from cr_items where item_id = :folder_id
+
+
+
+
+
+
+
+ update acs_objects
+ set context_id = :new_folder_id
+ where object_id = :folder_id
+
+
+
+
+
+
+
+
+ select name from cr_items where item_id = :folder_id
+
+
+
+
+
+
+
+ select count(*)
+ from cr_items
+ where name = :folder_name
+ and parent_id = :new_folder_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/index-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/index-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/index-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,59 @@
+
+
+
+ oracle8.1.6
+
+
+
+
+ select
+ cf.label as folder_name,
+ cf.description as folder_description,
+ decode(acs_permission.permission_p(cf.folder_id, :user_id, 'admin'),'t',1,0) as admin_p,
+ decode(acs_permission.permission_p(cf.folder_id, :user_id, 'pa_create_folder'),'t',1,0) as subfolder_p,
+ decode(acs_permission.permission_p(cf.folder_id, :user_id, 'pa_create_album'),'t',1,0) as album_p,
+ decode(acs_permission.permission_p(cf.folder_id, :user_id, 'write'),'t',1,0) as write_p,
+ decode(acs_permission.permission_p(ci.parent_id, :user_id, 'write'),'t',1,0) as parent_folder_write_p,
+ (select count(*) from dual where exists (select 1 from cr_items ci2 where ci2.parent_id = cf.folder_id)) as has_children_p,
+ decode(acs_permission.permission_p(cf.folder_id, :user_id, 'delete'),'t',1,0) as folder_delete_p
+ from cr_folders cf,
+ cr_items ci
+ where ci.item_id = cf.folder_id
+ and ci.item_id = :folder_id
+
+
+
+
+
+
+
+
+ select * from (
+ select i.item_id,
+ r.title as name,
+ r.description,
+ 'Album' as type,
+ 1 as ordering_key
+ from cr_items i,
+ cr_revisions r
+ where i.content_type = 'pa_album'
+ and i.parent_id = :folder_id
+ and i.live_revision = r.revision_id
+ UNION ALL
+ select i.item_id,
+ f.label as name,
+ f.description,
+ 'Folder',
+ 0
+ from cr_items i,
+ cr_folders f
+ where i.parent_id = :folder_id
+ and i.item_id = f.folder_id
+ )
+ where acs_permission.permission_p(item_id, :user_id, 'read') = 't'
+ order by ordering_key,name
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/index-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/index-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/index-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,57 @@
+
+
+
+ postgresql7.1
+
+
+
+ select
+ cf.label as folder_name,
+ cf.description as folder_description,
+ case when acs_permission__permission_p(cf.folder_id, :user_id, 'admin') = 't' then 1 else 0 end as admin_p,
+ case when acs_permission__permission_p(cf.folder_id, :user_id, 'pa_create_folder') = 't' then 1 else 0 end as subfolder_p,
+ case when acs_permission__permission_p(cf.folder_id, :user_id, 'pa_create_album') = 't' then 1 else 0 end as album_p,
+ case when acs_permission__permission_p(cf.folder_id, :user_id, 'write') = 't' then 1 else 0 end as write_p,
+ case when acs_permission__permission_p(ci.parent_id, :user_id, 'write') = 't' then 1 else 0 end as parent_folder_write_p,
+ (select count(*) where exists (select 1 from cr_items ci2 where ci2.parent_id = cf.folder_id)) as has_children_p,
+ case when acs_permission__permission_p(cf.folder_id, :user_id, 'delete') = 't' then 1 else 0 end as folder_delete_p
+ from cr_folders cf,
+ cr_items ci
+ where ci.item_id = cf.folder_id
+ and ci.item_id = :folder_id
+
+
+
+
+
+
+
+ select * from (
+ select i.item_id,
+ r.title as name,
+ r.description,
+ 'Album' as type,
+ 1 as ordering_key
+ from cr_items i,
+ cr_revisions r
+ where i.content_type = 'pa_album'
+ and i.parent_id = :folder_id
+ and i.live_revision = r.revision_id
+ UNION ALL
+ select i.item_id,
+ f.label as name,
+ f.description,
+ 'Folder',
+ 0
+ from cr_items i,
+ cr_folders f
+ where i.parent_id = :folder_id
+ and i.item_id = f.folder_id
+ ) as albums_and_folders
+ where acs_permission__permission_p(item_id, :user_id, 'read') = 't'
+ order by ordering_key,name
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/index.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/index.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,64 @@
+
+@folder_name@
+@context@
+
+
+
+ To order prints of these photos you will first need to add them
+ to a clipboard (you can do this when viewing an individual
+ photo). Once they are in a clipboard you can send them off to
+ shutterfly.com for
+ printing from a clipboard screen.
Index: openacs-4/packages/photo-album/www/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/index.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/index.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,89 @@
+# /packages/photo-album/www/index.tcl
+
+ad_page_contract {
+
+ Photo album front page. List the albums and subfolders in the folder specified
+ Uses package root folder if none specified
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/7/2000
+ @cvs-id $Id: index.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ {folder_id:integer [pa_get_root_folder]}
+} -validate {
+ valid_folder -requires {folder_id:integer} {
+ if [string equal [pa_is_folder_p $folder_id] "f"] {
+ ad_complain "The specified folder is not valid."
+ }
+ }
+} -properties {
+ context:onevalue
+ folder_name:onevalue
+ folder_description:onevalue
+ folder_id:onevalue
+ admin_p:onevalue
+ subfolder_p:onevalue
+ album_p:onevalue
+ write_p:onevalue
+ move_p:onevalue
+ delete_p:onevalue
+ child:multirow
+}
+
+
+# check for read permission on folder
+ad_require_permission $folder_id read
+
+set user_id [ad_conn user_id]
+set context [pa_context_bar_list $folder_id]
+
+# get all the info about the current folder and permissions with a single trip to database
+db_1row get_folder_info {}
+
+set root_folder_id [pa_get_root_folder]
+
+# to move an album need write on album and write on parent folder
+set move_p [expr $write_p && !($folder_id == $root_folder_id) && $parent_folder_write_p]
+
+# to delete an album, album must be empty, need delete on album, and write on parent folder
+set delete_p [expr !($has_children_p) && !($folder_id == $root_folder_id) && $folder_delete_p && $parent_folder_write_p]
+
+if $has_children_p {
+ db_multirow child get_childrenX "
+ select * from (
+ select i.item_id,
+ r.title as name,
+ r.description,
+ 'Album' as type,
+ 1 as ordering_key,
+ ic.image_id as iconic,
+ ic.width,
+ ic.height
+ from cr_items i,
+ cr_revisions r,
+ pa_albums a left outer join all_photo_images ic
+ on (ic.item_id = a.iconic and ic.relation_tag='thumb')
+ where i.content_type = 'pa_album'
+ and i.parent_id = :folder_id
+ and i.live_revision = r.revision_id
+ and a.pa_album_id = i.live_revision
+ UNION ALL
+ select i.item_id,
+ f.label as name,
+ f.description,
+ 'Folder',
+ 0,
+ null as iconic,0,0
+ from cr_items i,
+ cr_folders f
+ where i.parent_id = :folder_id
+ and i.item_id = f.folder_id
+ ) as x
+ where acs_permission__permission_p(item_id, :user_id, 'read') = 't'
+ order by ordering_key,name"
+} else {
+ set child:rowcount 0
+}
+
+set collections [db_string collections {select count(*) from pa_collections where owner_id = :user_id}]
+
Index: openacs-4/packages/photo-album/www/pa_master.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/pa_master.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/pa_master.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,10 @@
+
+Photo Album System : @title@
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-edit.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,103 @@
+# /packages/photo-album/www/photo-edit.tcl
+
+ad_page_contract {
+
+ Edit Photo Properties
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/11/2000
+ @cvs-id $Id: photo-edit.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ photo_id:integer,notnull
+} -validate {
+ valid_photo -requires {photo_id:integer} {
+ if [string equal [pa_is_photo_p $photo_id] "f"] {
+ ad_complain "The specified photo is not valid."
+ }
+ }
+} -properties {
+ path:onevalue
+ height:onevalue
+ width:onevalue
+}
+
+ad_require_permission $photo_id "write"
+
+set user_id [ad_conn user_id]
+set context_list [pa_context_bar_list -final "Edit Photo Attributes" $photo_id]
+
+template::form create edit_photo
+
+template::element create edit_photo photo_id -label "photo ID" \
+ -datatype integer -widget hidden
+
+template::element create edit_photo revision_id -label "revision ID" \
+ -datatype integer -widget hidden
+
+template::element create edit_photo previous_revision -label "previous_revision" \
+ -datatype integer -widget hidden
+
+template::element create edit_photo title -html { size 30 } \
+ -label "Photo Title" -optional -datatype text
+
+template::element create edit_photo caption -html { size 30 } \
+ -label "Caption" -help_text "Displayed on the thumbnail page" -optional -datatype text
+
+template::element create edit_photo description -html { size 50} \
+ -label "Photo Description" -help_text "Displayed when viewing the photo" -optional -datatype text
+
+template::element create edit_photo story -html { cols 50 rows 4 wrap soft } \
+ -label "Photo Story" -optional -datatype text -help_text "Displayed when viewing the photo" -widget textarea
+
+# moved outside is_request_block so that vars exist during form error reply
+
+db_1row get_photo_info {}
+
+set path $image_id
+
+if { [template::form is_request edit_photo] } {
+ set revision_id [db_string get_next_object_id "select acs_object_id_seq.nextval from dual"]
+ template::element set_properties edit_photo revision_id -value $revision_id
+ template::element set_properties edit_photo photo_id -value $photo_id
+ template::element set_properties edit_photo previous_revision -value $previous_revision
+ template::element set_properties edit_photo title -value $title
+ template::element set_properties edit_photo description -value $description
+ template::element set_properties edit_photo story -value $story
+ template::element set_properties edit_photo caption -value $caption
+}
+
+if { [template::form is_valid edit_photo] } {
+ set photo_id [template::element::get_value edit_photo photo_id]
+ set revision_id [template::element::get_value edit_photo revision_id]
+ set new_title [template::element::get_value edit_photo title]
+ set new_desc [template::element::get_value edit_photo description]
+ set new_story [template::element::get_value edit_photo story]
+ set new_caption [template::element::get_value edit_photo caption]
+ set previous_revision [template::element::get_value edit_photo previous_revision]
+ set peeraddr [ad_conn peeraddr]
+
+ db_transaction {
+ db_exec_plsql update_photo_attributes {}
+
+ db_dml insert_photo_attributes {}
+
+ # for now all the attributes about the specific binary file stay the same
+ # not allowing users to modify the binary yet
+ # will need to modify thumb and view binaries when photo binary is changed
+
+ db_dml update_photo_user_filename {}
+
+ db_exec_plsql set_live_revision {}
+
+ } on_error {
+ ad_return_complaint 1 "An error occurred while processing your input. Please let the system owner know about this.
+
$errmsg
"
+
+ ad_script_abort
+ }
+
+ ad_returnredirect "photo?photo_id=$photo_id"
+ ad_abort_script
+}
+
+ad_return_template
Index: openacs-4/packages/photo-album/www/photo-edit.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-edit.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,68 @@
+
+
+
+
+
+ select
+ ci.live_revision as previous_revision,
+ pp.caption,
+ pp.story,
+ cr.title,
+ cr.description,
+ i.height as height,
+ i.width as width,
+ i.image_id as image_id
+ from cr_items ci,
+ cr_revisions cr,
+ pa_photos pp,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+ where ci.live_revision = pp.pa_photo_id
+ and ci.live_revision = cr.revision_id
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ccr2.relation_tag = 'viewer'
+ and ci2.live_revision = i.image_id
+ and ci.item_id = :photo_id
+
+
+
+
+
+
+ insert into pa_photos (pa_photo_id, story, caption)
+ values
+ (:revision_id, :new_story, :new_caption)
+
+
+
+
+
+ UPDATE pa_photos
+ SET user_filename = prev.user_filename,
+ camera_model = prev.camera_model,
+ date_taken = prev.date_taken,
+ flash = prev.flash,
+ aperture = prev.aperture,
+ metering = prev.metering,
+ focal_length = prev.focal_length,
+ exposure_time = prev.exposure_time,
+ focus_distance = prev.focus_distance,
+ sha256 = prev.sha256,
+ photographer = prev.photographer
+ FROM (
+ SELECT user_filename,camera_model,date_taken,flash,
+ aperture,metering,focal_length,exposure_time,
+ focus_distance,sha256,photographer
+ FROM pa_photos prev
+ WHERE prev.pa_photo_id = :previous_revision
+ ) prev
+ WHERE pa_photo_id = :revision_id
+
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-iconic.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-iconic.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-iconic.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,35 @@
+ad_page_contract {
+ Make a given photo the iconic photo for the album.
+} {
+ photo_id:integer,notnull
+} -validate {
+ valid_photo -requires {photo_id:integer} {
+ if ![string equal [pa_is_photo_p $photo_id] "t"] {
+ ad_complain "The specified photo is not valid."
+ }
+ }
+}
+
+set album_id [db_string get_album_id {
+ SELECT a.item_id
+ FROM cr_items i, cr_items a
+ WHERE i.item_id = :photo_id
+ and a.item_id = i.parent_id
+ and i.content_type = 'pa_photo'
+ and i.live_revision is not null
+} -default 0]
+
+# If we did not get an album ID
+if {! $album_id } {
+ ad_return_error "Photo Internal Error" "The photo is either not live or not in an album. Please inform the webmaster of the error"
+}
+
+ad_require_permission $album_id "write"
+
+db_dml photo_iconic {
+ UPDATE pa_albums
+ SET iconic = :photo_id
+ WHERE pa_album_id = content_item__get_live_revision(:album_id)
+}
+
+ad_returnredirect "album?album_id=$album_id"
Index: openacs-4/packages/photo-album/www/photo-move-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-move-oracle.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-move-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,19 @@
+
+
+
+ oracle8.1.6
+
+
+
+ select r.title as name, i.item_id
+ from cr_items i, cr_revisions r
+ where i.live_revision = r.revision_id
+ and i.parent_id = (select parent_id from cr_items where item_id = :old_album_id)
+ and acs_permission.permission_p(i.item_id, :user_id, 'read') = 't'
+ and i.content_type = 'pa_album'
+ and i.item_id != :old_album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-move-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-move-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-move-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,19 @@
+
+
+
+ postgresql7.1
+
+
+
+ select r.title as name, i.item_id
+ from cr_items i, cr_revisions r
+ where i.live_revision = r.revision_id
+ and i.parent_id = (select parent_id from cr_items where item_id = :old_album_id)
+ and acs_permission__permission_p(i.item_id, :user_id, 'read') = 't'
+ and i.content_type = 'pa_album'
+ and i.item_id != :old_album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-move.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-move.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-move.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,7 @@
+
+@title@
+@context_list@
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-move.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-move.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-move.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,109 @@
+#/packages/photo-album/www/photo-move.tcl
+
+ad_page_contract {
+ Allows user to move a photo from one album to another album in the same folder
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/20/2000
+ @cvs-id $Id: photo-move.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ photo_id:integer,notnull
+} -validate {
+ valid_photo -requires {photo_id:integer} {
+ if [string equal [pa_is_photo_p $photo_id] "f"] {
+ ad_complain "The specified photo is not valid."
+ }
+ }
+}
+set context_list [pa_context_bar_list -final "Move Photo" $photo_id]
+set user_id [ad_conn user_id]
+
+# to move a photo need write on photo, and old parent album
+# and pa_create_photo on new parent album (which is check in the is_valid block)
+
+set old_album_id [db_string get_parent_album "select parent_id from cr_items where item_id = :photo_id"]
+ad_require_permission $photo_id write
+
+
+ad_require_permission $old_album_id write
+
+db_1row get_photo_info {}
+
+set path $image_id
+
+# build form
+
+template::form create move_photo
+
+template::element create move_photo photo_id -label "photo ID" \
+ -datatype integer -widget hidden
+
+template::element create move_photo new_album_id -label "Choose New Album for Photo" \
+ -datatype integer -widget select \
+ -options [db_list_of_lists get_albums {}]
+
+if { [template::form is_request move_photo] } {
+ template::element set_properties move_photo photo_id -value $photo_id
+}
+
+if { [template::form is_valid move_photo] } {
+ set new_album_id [template::element::get_value move_photo new_album_id]
+
+ ad_require_permission $new_album_id "pa_create_photo"
+
+ if [string equal [pa_is_album_p $new_album_id] "f"] {
+ # may add some sort of error message
+ # but this case only happens due to url hacking
+ # (or coding errors, which never happen)
+ ad_script_abort
+ }
+
+ db_transaction {
+
+ # not using content_item move because is only accepts
+ # a folder_id as target not another content_item
+
+ set rel_id [db_string photo_rel_id {}]
+
+ db_dml photo_move {}
+
+ db_dml photo_move2 {}
+
+ db_dml context_update {}
+
+ } on_error {
+ # most likely a duplicate name or a double click
+
+ set filename [db_string filename "
+ select name from cr_items where item_id = :photo_id"]
+
+ if [db_string duplicate_check "
+ select count(*)
+ from cr_items
+ where name = :filename
+ and parent_id = :new_album_id"] {
+ ad_return_complaint 1 "Either there is already a photo in the specified albumr with the name \"$filename\" or you clicked on the button more than once. You can return to the new album to see if your photo is there."
+ } else {
+ ad_return_complaint 1 "We got an error that we couldn't readily identify. Please let the system owner know about this.
+
+
$errmsg
"
+ }
+
+ ad_script_abort
+ }
+
+ pa_flush_photo_in_album_cache $old_album_id
+ pa_flush_photo_in_album_cache $new_album_id
+
+ #page used to redirect user to the page of new album containing moved photos
+ set page [pa_page_of_photo_in_album $photo_id $new_album_id]
+
+ ad_returnredirect "album?album_id=$new_album_id&page=$page"
+ ad_script_abort
+}
+
+ad_return_template
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo-move.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-move.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo-move.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,96 @@
+
+
+
+
+
+ select parent_id from cr_items where item_id = :photo_id
+
+
+
+
+
+
+ select
+ cr.title,
+ i.height as height,
+ i.width as width,
+ i.image_id as image_id
+ from cr_items ci,
+ cr_revisions cr,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+ where ci.live_revision = cr.revision_id
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ccr2.relation_tag = 'viewer'
+ and ci2.live_revision = i.image_id
+ and ci.item_id = :photo_id
+
+
+
+
+
+
+
+ select rel_id from cr_child_rels
+ where parent_id = :old_album_id
+ and child_id = :photo_id
+
+
+
+
+
+
+
+ update cr_items
+ set parent_id = :new_album_id
+ where item_id = :photo_id
+
+
+
+
+
+
+
+
+ update cr_child_rels
+ set parent_id = :new_album_id
+ where parent_id = :old_album_id
+ and child_id = :photo_id
+
+
+
+
+
+
+
+
+ update acs_objects
+ set context_id = :new_album_id
+ where object_id = :photo_id or object_id = :rel_id
+
+
+
+
+
+
+
+
+ select name from cr_items where item_id = :photo_id
+
+
+
+
+
+
+
+ select count(*)
+ from cr_items
+ where name = :filename
+ and parent_id = :new_album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,79 @@
+
+ @title@
+ @context@
+ 1
+
+ @photo_nav_html@
+
+
+
+ Save this photo to print or view later
+
+
+
+
+
+
+ This photo clipped to:
+
+ @clipped.title@ [remove]
+
+
+
+ View all your clipboards
+
+
+
+
Index: openacs-4/packages/photo-album/www/photo.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,78 @@
+# /packages/photo-album/www/photo.tcl
+
+ad_page_contract {
+
+ Photo display page.
+
+ @author Tom Baginski (bags@arsdigita.com)
+ @creation-date 12/10/2000
+ @cvs-id $Id: photo.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ photo_id:integer,notnull
+ {collection_id:integer,optional {}}
+} -validate {
+ valid_photo -requires {photo_id:integer} {
+ if [string equal [pa_is_photo_p $photo_id] "f"] {
+ ad_complain "The specified photo is not valid."
+ }
+ }
+} -properties {
+ context:onevalue
+ title:onevalue
+ description:onevalue
+ story:onevalue
+ caption:onevalue
+ path:onevalue
+ height:onevalue
+ width:onevalue
+ photo_nav_html:onevalue
+ admin_p:onevalue
+ write_p:onevalue
+ album_id:onevalue
+ page_num:onevalue
+ show_base_link:onevalue
+ clipboards:multirow
+}
+
+ad_require_permission $photo_id "read"
+
+set user_id [ad_conn user_id]
+set context [pa_context_bar_list $photo_id]
+
+# this is handled with a parameter rather than a permission on the
+# individual photo so admin can turn access on and off for entire
+# subsite at once. A permission would allow greater flexability, but
+# to shut down access to base photos an admin would need to search through
+# database and revoke all such permissions.
+set show_base_link [ad_parameter AllowBasePhotoAccessP]
+
+# query all the photo and permission info with a single trip to database
+if {![db_0or1row get_photo_info {}]} {
+ ad_return_complaint 1 "
photo not found"
+}
+
+set path $image_id
+
+# to move a photo need write on photo and write on parent album
+set move_p [expr $write_p && $album_write_p]
+
+# to delete a photo need delete on photo and write on parent album
+set delete_p [expr $photo_delete_p && $album_write_p]
+
+# determine what album page the photo is on so page can present link back to thumbnail page
+set page_num [pa_page_of_photo_in_album $photo_id $album_id]
+
+set photo_nav_html [pa_pagination_bar $photo_id [pa_all_photos_in_album $album_id] "photo?photo_id=" photo]
+
+pa_clipboards_multirow -create_new -force_default $user_id clipboards
+
+#proc pa_clipboards_get -photo_id $photo_id -multirow clipped
+
+db_multirow clipped get_clips {
+SELECT c.collection_id, c.title
+ FROM pa_collections c, pa_collection_photo_map m
+ WHERE m.photo_id = :photo_id
+ and m.collection_id = c.collection_id
+ and owner_id = :user_id
+ ORDER BY c.title
+}
Index: openacs-4/packages/photo-album/www/photo.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photo.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+select
+ pp.caption,
+ pp.story,
+ cr.title,
+ cr.description,
+ i.height as height,
+ i.width as width,
+ i.image_id as image_id,
+ ci.parent_id as album_id,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'admin') ='t' then 1 else 0 end as admin_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'write') = 't' then 1 else 0 end as write_p,
+ case when acs_permission__permission_p(ci.parent_id, :user_id, 'write') = 't' then 1 else 0 end as album_write_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'delete') = 't' then 1 else 0 end as photo_delete_p
+from cr_items ci,
+ cr_revisions cr,
+ pa_photos pp,
+ cr_items ci2,
+ cr_child_rels ccr2,
+ images i
+where cr.revision_id = pp.pa_photo_id
+ and ci.live_revision = cr.revision_id
+ and ci.item_id = ccr2.parent_id
+ and ccr2.child_id = ci2.item_id
+ and ccr2.relation_tag = 'viewer'
+ and ci2.live_revision = i.image_id
+ and ci.item_id = :photo_id
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photos-add-2.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photos-add-2.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-add-2.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1 @@
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/photos-add-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-add-2.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-add-2.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,79 @@
+# /packages/photo-album/www/photos-add-2.tcl
+ad_page_contract {
+ Upload a collection of photos from a tar or zip file.
+
+ Process and insert photos.
+
+ @author Jeff Davis (davis@xarg.net)
+ @creation-date 6/28/2002
+ @cvs_id $Id: photos-add-2.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ upload_file:trim,optional
+ upload_file.tmpfile:optional,tmpfile
+ directory:trim,optional
+ album_id:integer,notnull
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+ non_empty -requires {upload_file.tmpfile:notnull} {
+ if {![empty_string_p $upload_file] && (![file exists ${upload_file.tmpfile}] || [file size ${upload_file.tmpfile}] < 4)} {
+ ad_complain "The upload failed or the file was empty"
+ }
+ }
+ directory_exists -requires {directory:notnull} {
+ if {![empty_string_p $directory] && ![file isdirectory $directory]} {
+ ad_complain "The directory file does not exist"
+ }
+ }
+ directory_tmp -requires {directory:notnull} {
+ if {![empty_string_p $directory]
+ && !([ad_conn user_id] == 2599 || [ad_conn user_id] == 2601)
+ && ( ![string match "/tmp/pa-tmp" $directory ] || [string match ".." $directory]) } {
+ ad_complain "You can currently only load images from /tmp/pa-tmp for security"
+ }
+ }
+}
+
+#check permission
+set user_id [ad_conn user_id]
+
+ad_require_permission $album_id "pa_create_photo"
+
+if { ![empty_string_p $upload_file] &&
+ [ catch {set tmp_dir [pa_expand_archive $upload_file ${upload_file.tmpfile} pa-$album_id] } errMsg] } {
+ ad_return_complaint 1 "Unable to expand your archive file"
+ ad_script_abort
+}
+ReturnHeaders text/html
+ns_write "Upload Log
Upload log
\n"
+
+
+if {![empty_string_p $upload_file]} {
+ if {[info exists directory] && ![empty_string_p $directory]} {
+ ns_write "Uploading file only...please submit your directory based upload seperately "
+ }
+ ns_write "starting to load images from file $upload_file \n"
+ ns_log Debug "made directory $tmp_dir to extract from ${upload_file.tmpfile} ($upload_file)\n"
+ set allfiles [pa_walk $tmp_dir]
+ set remove 1
+} else {
+ ns_write "starting to load images from directory $directory \n"
+ set allfiles [pa_walk $directory]
+ set remove 0
+}
+
+set new_photo_ids [pa_load_images -remove $remove $allfiles $album_id $user_id]
+
+pa_flush_photo_in_album_cache $album_id
+
+set page [pa_page_of_photo_in_album [lindex $new_photo_ids 0] $album_id]
+ns_write "View the images"
+ns_write ""
+
+# Now that we are done working on the upload we delete the tmp file
+if [info exists tmp_dir] {
+ file delete -force $tmp_dir
+}
Index: openacs-4/packages/photo-album/www/photos-add.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-add.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-add.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,5 @@
+
+Upload a Photo collection
+@context@
+
+
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/photos-add.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-add.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-add.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,49 @@
+# /packages/photo-album/www/photos-add.tcl
+
+ad_page_contract {
+ Upload a collection of photos from a tar or zip file.
+ Initial form data
+
+ @author Jeff Davis (davis@xarg.net)
+ @creation-date 6/28/2002
+ @cvs_id $Id: photos-add.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+} -properties {
+ album_id:onevalue
+ context:onevalue
+}
+
+# check for read permission on folder
+ad_require_permission $album_id pa_create_photo
+
+set context [pa_context_bar_list -final "Upload photos" $album_id]
+
+set photo_id [db_string get_next_object_id "select acs_object_id_seq.nextval from dual"]
+
+template::form create photos_upload -action photos-add-2 -html {enctype multipart/form-data}
+
+template::element create photos_upload album_id \
+ -label "album_id" -datatype integer -widget hidden
+
+template::form::section photos_upload Either
+
+template::element create photos_upload upload_file \
+ -label "Choose a tar or zip file to upload" -help_text "Use the \"Browse...\" button to locate your file, then click \"Open\"" -datatype text -widget file
+
+template::form::section photos_upload Or
+
+template::element create photos_upload directory -html { size 50} \
+ -label "Or choose a server directory to upload" -help_text "the directory must exist on server and be readable by the server process" -datatype text -widget text
+
+template::element set_properties photos_upload album_id -value $album_id
+
+ad_return_template
+
+
Index: openacs-4/packages/photo-album/www/photos-add.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-add.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-add.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+ select acs_object_id_seq.nextval from dual
+
+
+
+
Index: openacs-4/packages/photo-album/www/photos-edit-2.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-edit-2.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-edit-2.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,8 @@
+
+@title@
+@context_list@
+
+Your text updates have been made and any rotations are
+currently being processed...
+
+@page_nav@
Index: openacs-4/packages/photo-album/www/photos-edit-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-edit-2.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-edit-2.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,104 @@
+ad_page_contract {
+ Bulk edit a set of images.
+} {
+ album_id:integer,notnull
+ {page:integer,notnull "1"}
+ d:array,integer,optional
+ hide:array,optional
+ caption:array
+ story:array
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+}
+
+set context_list [pa_context_bar_list -final "Edit page $page" $album_id]
+
+set hides [list]
+set shows [list]
+foreach id [array names caption] {
+ # create a list of hide and show images.
+ if {[info exists hide($id)]} {
+ lappend hides $id
+ } else {
+ lappend shows $id
+ }
+
+ set acaption $caption($id)
+ set astory $story($id)
+
+ db_dml update_photo {
+ update pa_photos
+ set caption = :acaption,
+ story = :astory
+ where pa_photo_id = (select latest_revision from cr_items where item_id = :id)
+ }
+
+ if {[llength $hides]} {
+ db_dml update_hides "update cr_items set live_revision = null where item_id in ([join $hides ,])"
+ }
+ if {[llength $shows]} {
+ db_dml update_shows "update cr_items set live_revision = latest_revision where item_id in ([join $shows ,])"
+ }
+
+}
+
+pa_flush_photo_in_album_cache $album_id
+
+ad_returnredirect "album?album_id=$album_id&page=$page&msg=1"
+
+proc pa_rotate {id rotation} {
+ if {![empty_string_p $rotation] && ![string equal $rotation 0]} {
+ set flop [list]
+ set files [list]
+
+ # get a list of files to handle sorted by size...
+ db_foreach get_image_files {
+ select i.image_id, crr.content, i.width, i.height
+ from cr_items cri, cr_revisions crr, images i
+ where cri.parent_id = :id
+ and crr.revision_id = cri.latest_revision
+ and i.image_id = cri.latest_revision
+ order by crr.content_length desc
+ } {
+ ns_log Notice "pa_rotate $id $rotation [cr_fs_path] $content $image_id $width $height"
+ if {[catch {exec convert -rotate $rotation [cr_fs_path]$content [cr_fs_path]${content}.new } errMsg]} {
+ ns_log Notice "Failed rotation of image $image_id -- $errMsg"
+ }
+ lappend flop $image_id
+ lappend files [cr_fs_path]$content
+ }
+
+ # rename files in catch.
+ if { [catch {
+ foreach fnm $files {
+ file rename -force $fnm ${fnm}.old
+ file rename -force ${fnm}.new $fnm
+ } } errMsg ] } {
+ # problem with the renaming. Make an attempt to rename them back
+ catch {
+ foreach fnm $files {
+ file rename -force ${fnm}.old $fnm
+ file delete -force ${fnm}.new
+ }
+ } errMsg
+ } else {
+ # flop images that need flopping.
+ if {[string equal $rotation 90] || [string equal $rotation 270]} {
+ db_dml flop_image_size "update images set width = height, height = width where image_id in ([join $flop ,])"
+ }
+ }
+ }
+}
+
+
+foreach id [array names d] {
+ if { $d($id) > 0 } {
+ pa_rotate $id $d($id)
+ }
+}
+
+ad_script_abort
Index: openacs-4/packages/photo-album/www/photos-edit-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-edit-postgresql.xql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-edit-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,27 @@
+
+
+
+ postgresql7.1
+
+
+
+select cr.title,
+ cr.description,
+ pa.story,
+ ci.parent_id as parent_folder_id,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'admin') = 't' then 1 else 0 end as admin_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'pa_create_photo') = 't' then 1 else 0 end as photo_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'write') ='t' then 1 else 0 end as write_p,
+ case when acs_permission__permission_p(ci.parent_id, :user_id, 'write') = 't' then 1 else 0 end as folder_write_p,
+ case when acs_permission__permission_p(ci.item_id, :user_id, 'delete') = 't' then 1 else 0 end as album_delete_p
+from cr_items ci,
+ cr_revisions cr,
+ pa_albums pa
+where ci.live_revision = cr.revision_id
+ and ci.live_revision = pa_album_id
+ and ci.item_id = :album_id
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/photos-edit.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-edit.adp,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-edit.adp 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,72 @@
+
+@title@
+@context_list@
+
+
+@page_nav@
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/photos-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photos-edit.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/photos-edit.tcl 10 Jun 2003 10:07:11 -0000 1.1
@@ -0,0 +1,157 @@
+# packages/photo-album/www/photos-edit.tcl
+
+ad_page_contract {
+ Bulk edit photos in a given album
+
+ @author Jeff Davis (davis@xarg.net)
+ @creation-date 7/1/2002
+ @cvs-id $Id: photos-edit.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $
+} {
+ album_id:integer,notnull
+ {page:integer,notnull "1"}
+} -validate {
+ valid_album -requires {album_id:integer} {
+ if [string equal [pa_is_album_p $album_id] "f"] {
+ ad_complain "The specified album is not valid."
+ }
+ }
+} -properties {
+ album_id:onevalue
+ title:onevalue
+ description:onevalue
+ story:onevalue
+ context_list:onevalue
+ child_photo:multirow
+ page_nav:onevalue
+ admin_p:onevalue
+ photo_p:onevalue
+ write_p:onevalue
+ move_p:onevalue
+ delete_p:onevalue
+}
+
+set user_id [ad_conn user_id]
+
+# check for read permission on album
+ad_require_permission $album_id read
+
+set context_list [pa_context_bar_list -final "Edit page $page" $album_id]
+
+db_1row get_album_info {
+select cr.title,
+ cr.description,
+ pa.story,
+ ci.parent_id as parent_folder_id,
+ decode(acs_permission.permission_p(ci.item_id, :user_id, 'admin'),'t',1,0) as admin_p,
+ decode(acs_permission.permission_p(ci.item_id, :user_id, 'pa_create_photo'),'t',1,0) as photo_p,
+ decode(acs_permission.permission_p(ci.item_id, :user_id, 'write'),'t',1,0) as write_p,
+ decode(acs_permission.permission_p(ci.parent_id, :user_id, 'write'),'t',1,0) as folder_write_p,
+ decode(acs_permission.permission_p(ci.item_id, :user_id, 'delete'),'t',1,0) as album_delete_p
+from cr_items ci,
+ cr_revisions cr,
+ pa_albums pa
+where ci.live_revision = cr.revision_id
+ and ci.live_revision = pa_album_id
+ and ci.item_id = :album_id
+}
+# to move an album need write on album and write on parent folder
+set move_p [expr $write_p && $folder_write_p]
+
+# to delete an album, album must be empty, need delete on album, and write on parent folder
+set has_children_p [expr [pa_count_photos_in_album $album_id] > 0]
+set delete_p [expr !($has_children_p) && $album_delete_p && $folder_write_p]
+
+set photos_on_page [pa_all_photos_on_page $album_id $page]
+
+if {$has_children_p && [llength $photos_on_page] > 0} {
+ # query gets all child photos in album
+ # I query the data without an orderby in the sql to cut the querry time
+ # and then sort the returned data manually while constructing the multirow datasource.
+ # This goes against the theory of let oracle do the hard work, but load testing and
+ # query tuning showed that the order by doubled the query time while sorting a few rows in tcl was fast
+
+ # wtem@olywa.net, 2001-09-24
+ set photo_sql "
+ select ci.item_id as photo_id,
+ pp.caption,
+ pp.story,
+ to_char(pp.date_taken, 'MM/DD/YYYY HH:MI') as datetaken,
+ pp.camera_model,
+ pp.focal_length,
+ pp.aperture,
+ pp.exposure_time,
+ pp.flash,
+ it.image_id as thumb_path,
+ it.height as thumb_height,
+ it.width as thumb_width,
+ iv.image_id as viewer_path,
+ iv.height as viewer_height,
+ iv.width as viewer_width
+ from cr_items ci,
+ cr_items cit,
+ cr_child_rels ccrt,
+ images it,
+ cr_items civ,
+ cr_child_rels ccrv,
+ images iv,
+ pa_photos pp
+ where
+ ccrt.relation_tag = 'thumb'
+ and ci.item_id = ccrt.parent_id
+ and ccrt.child_id = cit.item_id
+ and cit.live_revision = it.image_id
+ and ccrv.relation_tag = 'viewer'
+ and ci.item_id = ccrv.parent_id
+ and ccrv.child_id = civ.item_id
+ and civ.live_revision = iv.image_id
+ and pp.pa_photo_id = ci.live_revision
+ and ci.item_id in ([join $photos_on_page ","])"
+
+ db_foreach get_child_photos $photo_sql {
+ set val(photo_id) $photo_id
+ set val(caption) $caption
+ set val(story) $story
+ set val(datetaken) $datetaken
+ set val(camera_model) $camera_model
+ set val(focal_length) $focal_length
+ set val(aperture) $aperture
+ set val(flash) $flash
+ set val(exposure_time) $exposure_time
+ set val(thumb_path) $thumb_path
+ set val(thumb_height) $thumb_height
+ set val(thumb_width) $thumb_width
+ set val(viewer_path) $viewer_path
+ set val(viewer_height) $viewer_height
+ set val(viewer_width) $viewer_width
+ set val(window_height) [expr $viewer_height + 28]
+ set val(window_width) [expr $viewer_width + 24]
+ set child($photo_id) [array get val]
+ }
+
+ # if the structure of the multirow datasource ever changes, this needs to be rewritten
+ set counter 0
+ foreach id $photos_on_page {
+ if {[info exists child($id)]} {
+ incr counter
+ set child_photo:${counter}(rownum) $counter
+ foreach {key value} $child($id) {
+ set child_photo:${counter}($key) $value
+ }
+ }
+ }
+
+ set child_photo:rowcount $counter
+
+ set total_pages [pa_count_pages_in_album $album_id]
+
+ for {set i 1} {$i <= $total_pages} {incr i} {
+ lappend pages $i
+ }
+ set page_nav [pa_pagination_bar $page $pages "photos-edit?[export_vars -url {album_id}]&page="]
+
+
+} else {
+ # don't bother querying for children if we know they don't exist
+ set child_photo:rowcount 0
+ set page_nav ""
+}
Index: openacs-4/packages/photo-album/www/doc/acs-admin-guide.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/acs-admin-guide.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/doc/acs-admin-guide.html 10 Jun 2003 10:07:46 -0000 1.1
@@ -0,0 +1,187 @@
+
+
Imagemagick The convert and identify
+ binaries must be installed within the location specified by the parameter
+ ImageMagickPath. The user that the webserver is running under must have
+ execute privileges for the files. A link to a download page for ImageMagick
+ can be found in the design document.
+
Image Storage Directory The photo album
+ store image binaries in the file system. The webserver user must have read,
+ write, and execute privileges for the directory specified in the parameter PhotoDir.
+ This directory must be in the acs root directory for the server. The webserver
+ user must also have write privilege on any file created in this directory or it
+ will not be able to delete images.
+
Permission Checks for Serving Images The parameter
+ CheckPermissionOnImageServeP controls if images/index.vuh queries the database to
+ check if user has read permission on a photo prior to serving it. Setting this to true
+ will slow server performance because it causes an extra trip to the database for every
+ image served. Default album pages serve 12 thumbnails per page, which translates into 12
+ extra trips to the database. Users should not be presented a link/img tag for an image
+ for which they do not have read privileges. Unless you are really concerned about someone
+ url hacking to a private image (which they would need to know the full path), I suggest
+ leaving this parameter set to false.
+
The basic content element of the photo album system is a photo.
+ When a user uploads a photo, the system stores attribute
+ data such as caption, story, and title as a
+ single content element. Each photo associated with several
+ (three to start) image elements that store the actual binary files.
+ The image elements, which are created by the server, are standard sized
+ versions of the original photo used for display. Photos and images
+ can have descriptive attributes associated with them. The attributes
+ and binary files can be revised and the system will retain past
+ versions.
Photos are grouped together into albums which can contain 0 or
+ more photos. The albums can have descriptive attribute information
+ that can be revised with history tracking. The albums can be
+ displayed as a unit that allows user to browse through the photos
+ in the album.
Albums can be grouped together into folders that can contain 0
+ or more albums or other folders.
An instance of the package include pages to display the folders,
+ albums, and photos along with admin pages. Instances can be mounted
+ to different subsite and managed independently. The grouping is
+ included within the instance so that the albums maintain a
+ consistent url even if they are re-sorted to different folders
+ within the instance (as long as the subsite url isn't changed).
The display, grouping, and administration functionality of the
+ photo album package will be included in the initial release of the
+ package. This is intended to be one part of a larger system that
+ will allow bulk uploading and purchasing of photos. These two
+ feature have already been implemented on aD customer sites. ACS 4
+ versions of these features will be either incorporated into a
+ future version of the photo album package or added as individual
+ packages that depend on the photo album.
The basic tasks of the photo album revolve around storing and
+ displaying content and associated attributes. As such, this package
+ will take advantage of the exiting features of the content
+ repository service package. The content repository can store
+ multiple revisions of content items such as photos and images and
+ their associated attributes. The content repository also provides
+ grouping functions. The acs permission service will be used for
+ access control so view, edit, and administration privileges will be
+ highly customizable. Finally individual photo album instances can
+ be added to subsites to support multiple independent photo albums
+ on the same site.
The the development of photo album package was base largely on
+ the experience of building a custom photo album application for the
+ Iluvcamp client site. The Iluvcamp photo album was built using an
+ early version of the content repository. The photo album package
+ uses the current version of the ACS content repository and takes
+ advantage of several key features of the ACS4 structure such as
+ permissions, templating, the content repository. The photo album
+ package avoid several of the limitation of the Iluvcamp Photo Album
+ that were made clear after supporting a summer of use and uploading
+ over 70GB of original photos.
A photodb application was developed for ACS 3.x. The option of
+ porting the photodb application to ACS4 was not followed due to the
+ customized nature of the photodb application. It was primarily
+ designed for storing and displaying information about photos for
+ photographers. In contrast, the photo album application provides a
+ general system for storing and displaying user uploaded photos,
+ which can be customized to any particular client application.
Not done. A google search for "photo album web application"
+ returns links for several shareware photo album applications.
+ I did not install or test any of these.
The package uses/requires the convert and identify
+ ImageMagick
+ binaries to be installed on the host computer at the location
+ specified in the ImageMagickPath parameter. ImageMagick is readily
+ available and easy to use from within server pages. ImageMagick is
+ copyrighted by ImageMagick Studio, a nonprofit organization.
+ ImageMagick is available for free, may be used to support both open
+ and proprietary applications, and may be redistributed without fee.
+ The previous ImageMagick Homepage has some mention of LZW patent
+ issues and redirects to a new location. If these patent issues
+ become a problem, the package will need to be re-coded to use
+ different image manipulation software.
By default the package stores the image binary files in the file
+ system. This decision was made for ease of use and development.
+ This was also based on the assumption that file system storage is
+ more appropriate for large systems with many giga-bytes of photos.
+ The content repository also provides support for database storage
+ of binaries in blobs. Future version of the photo album will also
+ support database storage of photos. Load testing will be used to
+ determine the most appropriate storage method for small and large
+ volumes of photos.
The default photo storage directory is outside of the page root
+ and images are served using a .vuh file. This was done to prevent
+ potential execution of user uploaded files. Although the package
+ checks that the user only uploads image files, in theory a rouge
+ user could upload a code file. If that file was directly accessible
+ from the page root, the rouge user could execute arbitrary code
+ with all the authority of the web server user. Serving the image
+ through a .vuh file also allows for checking access permissions to
+ a file before it is served to the user. The benefits of serving
+ image files with a .vuh file comes at a cost of some additional
+ server resources. Again, load testing will be used to determine the
+ true cost of using a .vuh file.
The photo attribute information and binary files are stored in
+ two different content types (pa_photos and pa_images). The linkage
+ between the binaries and the attribute info is maintained as a
+ relationship between the two content_items. This decision was made
+ so the the number of image sizes per photo could be changed with minor
+ code revision and no datamodel changes. This flexibility comes at a
+ cost, the queries to retreive and serve the appropriate version of
+ a photo need to join in several tables to do so. There also is not
+ an easy way to store the relation between different versions of the
+ photo-attribute info such as caption and the versions of the binaries.
The PL/SQL database api is incorporated into four packages: pa_image,
+ pa_photo, pa_album, and photo_album. The first three correspond to the
+ 3 new object types created for the photo album application. The last
+ contains general database functions for the application.
pa_image package
+
+
pa_image.new creates a new pa_image object type and returns the
+ cr_item.item_id of the newly created object. It also create the first revision
+ of that object. It accepts an item_id and revision_id as arguments but both
+ will be created if not provided. Although relation tag defaults to null it
+ should be in (thumb, viewer, base). Path is the path to the image binary relative
+ to the upload base (a parameterized directory).
+ function new (
+ name in cr_items.name%TYPE,
+ parent_id in cr_items.parent_id%TYPE default null,
+ item_id in acs_objects.object_id%TYPE default null,
+ revision_id in acs_objects.object_id%TYPE default null,
+ content_type in acs_object_types.object_type%TYPE default 'pa_image',
+ creation_date in acs_objects.creation_date%TYPE default sysdate,
+ creation_user in acs_objects.creation_user%TYPE default null,
+ creation_ip in acs_objects.creation_ip%TYPE default null,
+ locale in cr_items.locale%TYPE default null,
+ context_id in acs_objects.context_id%TYPE default null,
+ title in cr_revisions.title%TYPE default null,
+ description in cr_revisions.description%TYPE default null,
+ mime_type in cr_revisions.mime_type%TYPE default null,
+ nls_language in cr_revisions.nls_language%TYPE default null,
+ relation_tag in cr_child_rels.relation_tag%TYPE default null,
+ is_live in char default 'f',
+ publish_date in cr_revisions.publish_date%TYPE default sysdate,
+ path in pa_images.path%TYPE,
+ height in pa_images.height%TYPE default null,
+ width in pa_images.width%TYPE default null,
+ file_size in pa_images.file_size%TYPE default null
+ ) return cr_items.item_id%TYPE;
+
+
pa_image.delte_revision deletes a specified revision
+ of a pa_image and schedules the binary for deleation from the file-system by a sweep procedure
+
pa_photo.delete deletes a pa_photo object,
+ all revision of a pa_photo, and all associated pa_images (including binaries). Basically nukes
+ a photo, so be careful using this one, because it can't be undone.
pa_album.new creates a new pa_album object type and returns the
+ cr_item.item_id of the newly created object. It also create the first revision
+ of that object. It accepts an item_id and revision_id as arguments but both
+ will be created if not provided.
+ function new (
+ name in cr_items.name%TYPE,
+ album_id in cr_items.item_id%TYPE default null,
+ parent_id in cr_items.parent_id%TYPE default null,
+ revision_id in cr_revisions.revision_id%TYPE default null,
+ content_type in acs_object_types.object_type%TYPE default 'pa_album',
+ is_live in char default 'f',
+ creation_date in acs_objects.creation_date%TYPE default sysdate,
+ creation_user in acs_objects.creation_user%TYPE default null,
+ creation_ip in acs_objects.creation_ip%TYPE default null,
+ locale in cr_items.locale%TYPE default null,
+ context_id in acs_objects.context_id%TYPE default null,
+ relation_tag in cr_child_rels.relation_tag%TYPE default null,
+ publish_date in cr_revisions.publish_date%TYPE default sysdate,
+ mime_type in cr_revisions.mime_type%TYPE default null,
+ nls_language in cr_revisions.nls_language%TYPE default null,
+ title in cr_revisions.title%TYPE default null,
+ description in cr_revisions.description%TYPE default null,
+ story in pa_albums.story%TYPE default null
+ ) return cr_items.item_id%TYPE;
+
pa_album.delte_revision deletes a specified revision
+ of a pa_album
pa_album.delete deletes a pa_album and all revisions
+ of that album. The album must not have any child pa_phots or the delete throws an error. So
+ there is nothing equilent to rm -r *. You separately delete the
+ photos in an album (or move them to a different album) then delete the album.
photo_album.get_root_folder returns the root folder
+ for a given package_id (package instance). The root folder for a package is actually cached by the
+ web server. So it is probably faster to call the server proc pa_get_root_folder and pass the value
+ in as a bind variable any place you need the root_folder in a query.
+ function get_root_folder (
+ package_id in apm_packages.package_id%TYPE
+ ) return pa_package_root_folder_map.folder_id%TYPE;
+
The public procedural API available from the webserver is currently
+ implemented as tcl procedures.
pa_get_root_folder {package_id ""}
+ Returns the folder_id of the root folder for an instance of the photo album system.
+ If no root folder exists, as when a new package instance is accessed for the first time,
+ a new root folder is created automatically with appropriate permissions
+ If value has be previously requested, value pulled from cache. If pakage_id is not specified,
+ procedure uses value from [ad_conn package_id]
+
pa_context_bar_list {-final ""} item_id
+ Constructs the list to be fed to ad_context_bar appropriate for
+ item_id. If -final is specified, that string will be the last
+ item in the context bar. Otherwise, the name corresponding to
+ item_id will be used.
+
pa_make_file_name {-assert:boolean} {-ext ""} id
+ Constructs a filename for an image based on id and extention.
+ Files are created into a 3 tier directory structure: year/xx/zz/ for a photo_id 1234xxzz.jpg
+ Same file would return year/xx/zz/1234xxzz.jpg.
+ If -assert specified, proc creates directory and any parent directories if necessary
+
pa_is_folder_p folder_id {package_id ""}
+ Returns "t" if folder_id is a folder that is a child of the root folder for the package,
+ else "f". If package_id is not given procedure uses value from
[ad_conn package_id].
+
pa_is_album_p album_id {package_id ""}
+ Returns "t" if album_id is a album that is a child of the root folder for the package,
+ else "f" If package_id is not given procedure uses value from
[ad_conn package_id].
+
pa_is_photo_p photo_id {package_id ""}
+ Returns "t" if photo_id is a photo that is a child of the root folder for the package,
+ else "f" If package_id is not given procedure uses value from
[ad_conn package_id].
+
pa_grant_privilege_to_creator object_id {user_id ""}
+ Grants a set of default privileges stored in parameter PrivilegeForCreator
+ on object id to user_id. If user_id is not specified, uses current user.
+
pa_image_width_height filename width_var height_var
+ Uses ImageMagick program to get the width and height in pixels of filename.
+ Sets height to the variable named in height_var in the calling level.
+ Sets width_var to the variable named in width_var in the calling level.
+
+ I Use ImageMagick instead of aolsever funcition because it can handle more than
+ just gifs and jpegs.
+
pa_make_new_image base_image new_image max_width {max_height ""}
+ Uses ImageMagick program to create a file named new_image from base_image that
+ fits within a box defined by max_width by max_height (in pixels).
+ ImageMagick will retain the aspect ratio of the base_image when creating the new_image
+ If max_height is not specified, max_width is used for max_height.
+
pa_all_photos_in_album album_id
+ Returns a list of all the photo_ids in an album sorted in ascending order.
+ Pulls value from cache if already there, caches result and returns result if not
+
pa_count_photos_in_album album_id
+ Returns count of number of photos in album_id
+
pa_all_photos_on_page album_id page
+ Returns a list of the photo_ids on page page of album_id.
+ List is in ascending order
+
pa_count_pages_in_album album_id
+ Returns the number of pages in album_id
+
pa_page_of_photo_in_album photo_id album_id
+ Returns the page number of a photo in an album. If photo is not in the album returns -1
+
pa_flush_photo_in_album_cache album_id
+ Clears the cacheed value set by pa_all_photos_in_album for a single album
+ Call proc on any page that alters the number or order of photos in an album.
+
pa_pagination_page_number_links page total_pages
+ Returns html table fragament for navigating pages of an album.
+
pa_photo_number_links cur_id all_ids
+ Given a current photo_id and and an ordered list of all the photo_id in an album,
+ creates an html fragment that allows user to navigate to any photo by number,
+ or next/previous. Pulls url from connection so should work on page showing a single photo
+ based on photo_id (such as viewer size display page or base size display page).
+
The data model defines 3 new content types within the content
+ repository. These are pa_album, pa_photo, and pa_image. It uses the
+ exiting content_folder for grouping pa_albums. Pa_albums store
+ attribute information about a group of photos and serves as a
+ container for 0 or more photos. Pa_photos store attributes of user uploaded
+ photo. Pa_images are used as a helper type to store the base (original),
+ thumbnail and viewer display images associated
+ with a pa_photo. Each pa_photo has one child pa_image for its
+ base photo, one for its thumbnail image, and one child pa_image for its viewer image. The
+ pa_images are created by the server whenever a pa_photo is added
+ or edited.
The root folder for each package instance is stored in pa_root_folder_package_map.
+ All folders, albums, photos, and images within a package instance are
+ decendants of the root folder for that package.
Image files scheduled for deletion are stored in pa_files_to_delete. A
+ nightly web-server process deletes the files in this table and then removes
+ them from the table. This table allows images to be deleted transactionally from
+ both the database and the file-system. All photo/image delete operations should
+ add the binary file-name to pa_files_to_delete and then delete the attribute information
+ in the database within a transaction. This way the file system delete will not
+ happen unless the database delete succeeds.
The user accessible pages contain a set of pages for displaying,
+ adding, and editing folders, albums, and photos. The folder page
+ which serves as the index page allows a user to navigate to
+ sub-folders and albums within the folder. The album page displays
+ the photos (or a sub-set of photos) within an album. The photo page
+ displays a single photo.
Parameters are set by default through the apm and can be
+ edited by a user with admin privileges for a sub-site through the
+ current sub-site admin pages. Depending on which version of the
+ apm is installed, the server may need to be restarted for
+ the parameters of a new package instance are available.
The defined parameters are as follows:
ImageMagickPath
Description: Absolute path from computer root to directory
+ containing ImageMagick executables convert and identify.
Default: /usr/local/bin
PhotoDir
Description: Relative path from acs_root_dir to directory for
+ storing uploaded images. (do not include leading or trailing
+ forward slash)
Default: uploaded-photos
FullTempDir
Description: Absolute path from computer root to path for
+ temporary photos.
Default: /tmp/photo-album
PhotoStorageMethod
Description: Default method for storing photos, file-system or
+ database. (Package currently only supports file-system)
Default: file-system
ThumbnailSize
Description: Max Dimension for thumbnail image
Default: 100
ViewerSize
Description: Max Dimension for viewer images
Default: 400
ThumbnailsPerPage
Description: Number of thumbnail images to be displayed per album
+ page
Default: 12
PrivilegeForCreator
Description: CSV of privileges to grant to creators of new objects
+ within photo album
Default: admin
AcceptableUploadMIMETypes
Description: CSV of acceptable MIME Types for Photo Upload
Default: image/jpeg,image/gif
DefaultRootFolderPrivileges
Description: List of grantee privilege pairs for new root folders.
+ Grantee is an integer or function that returns a party_id. Format
+ as a space separated list
Description: If set to "t", users are presented a link to
+ display the full sized base image from photo page.
Default: t
CheckPermissionOnImageServeP
If set to "t", the images/index.vuh file runs a query to check
+ if user has read access to photo prior to serving it. Note, setting to
+ "t" can impact performance on high volume sites. The urls for images
+ also change depending on this parameter. If "t" url contains the
+ pa_image_id, else contains the path to the pa_image in file-system.
This document presents the requirements for the ACS 4.0 Photo
+ Album Package, which is a generalized application for storing and
+ displaying groups of photos on a web site. It is intended to build
+ on the experience gained from creating and maintaining a photo
+ album system for the IluvCamp client site.
Many people want to display photos on the web. Building a simple
+ personal web page with vacation photos is easy and can be done by
+ hand with static html. Building 100 similar web pages for all your
+ friends and relatives would be tedious. More importantly it would
+ be difficult to maintain and scale such a system to support all the
+ users of a large site.
The photo album package provides a convenient and uniform system
+ for uploading, storing, and displaying groups of photos on a web
+ site. It removes the tedious part of building pages to display
+ photos, and allows users more flexibility to maintain and modify
+ their own photo albums. It also removes much of the burden from the
+ owners/maintainers of the site. All of these factors add up to a
+ system that allows community members to easily contribute and view
+ large amounts of compelling content on a site.
The initial version of the package will allow designated users
+ to upload photos into albums and to group albums into a folder
+ hierarchy that other users with appropriate permissions can view
+ and possibly edit.
Future improvement to the photo album package will incorporate
+ additional features developed on various customer sites that allow
+ users to upload photos in bulk through a client applet and to
+ purchase prints of photos presented on the site.
The basic content element of the photo album system is a photo.
+ When a user uploads a photo, the system stores attribute
+ data such as caption, story, and title as a
+ single content element. Each photo associated with several
+ (three to start) image elements that store the actual binary files.
+ The image elements, which are created by the server, are standard sized
+ versions of the original photo used for display. Photos and images
+ can have descriptive attributes associated with them. The attributes
+ and binary files can be revised and the system will retain past
+ versions.
Photos are grouped together into albums which can contain 0 or
+ more photos. The albums can have descriptive attribute information
+ that can be revised with history tracking. The albums can be
+ displayed as a unit that allows user to browse through the photos
+ in the album.
Albums can be grouped together into folders that can contain 0
+ or more albums or other folders.
An instance of the package include pages to display the folders,
+ albums, and photos along with admin pages. Instances can be mounted
+ to different subsite and managed independently. The grouping is
+ included within the instance so that the albums maintain a
+ consistent url even if they are re-sorted to different folders
+ within the instance (as long as the subsite url isn't changed).
The display, grouping, and administration functionality of the
+ photo album package will be included in the initial release of the
+ package. This is intended to be one part of a larger system that
+ will allow bulk uploading and purchasing of photos. These two
+ feature have already been implemented on aD customer sites. ACS 4
+ versions of these features will be either incorporated into a
+ future version of the photo album package or added as individual
+ packages that depend on the photo album.
The basic tasks of the photo album revolve around storing and
+ displaying content and associated attributes. As such, this package
+ will take advantage of the exiting features of the content
+ repository service package. The content repository can store
+ multiple revisions of content items such as photos and images and
+ their associated attributes. The content repository also provides
+ grouping functions. The acs permission service will be used for
+ access control so view, edit, and administration privileges will be
+ highly customizable. Finally individual photo album instances can
+ be added to subsites to support multiple independent photo albums
+ on the same site.
A young couple just got married. His family shot 20 rolls of
+ film at the wedding and the photographer they hired shot an
+ additional 15 rolls. Now that the wedding is over, this couple must
+ organize their photos. In addition to creating traditional,
+ physical photo albums, they want to publish their photos on the web
+ to share with friends and family all over the world.
The couple scans the images they want to publish on the web.
+ Most of the images were scanned from the negatives at processing
+ time making it easy for the couple to obtain digital versions of
+ their photographs. The couple creates a new photo album for their
+ wedding, and then adds the following folders: "Engagement photo
+ shoot," "Rehearsal dinner," "Ceremony," "Reception," and
+ "Honeymoon." The honeymoon itself was spent in two different
+ places. The couple creates subfolders for each of these places in
+ their Honeymoon folder.
The couple now opens a folder, and uploads images. With each
+ image, the couple can specify optional attributes such as the
+ caption for the photo, the story behind the photo, and an
+ identifier to help them locate the physical negatives at a later
+ date.
Once the images are uploaded, the couple decides to give their
+ parents administrative access to a couple folders. Now their
+ parents can upload additional photos to those folders or modify the
+ attributes of any given photo.
�
The administrator of the "Dogs of the World" subsite on the
+ "All Furry Creatures" web sites wants to provide a way to show
+ pictures of various dog breads. Since the admin is a busy person
+ she doesn't want to upload and manage all of the images herself.
+ She does, however, want to specify the general layout of the
+ various albums and control who can upload images.
She creates an instance of the photo album within her subsite.
+ Then goes about creating a folder structure such as:
+ - Dogs of the World
+ -Hunting Dogs
+ -Show Dogs
+ -Lap Dogs
+ -Yappy Dogs
+ -Mutts(The coolest)
+
She then designates certain users or groups of users that she
+ trusts to manage a given folder and grants them permission to
+ create albums within each folder. These users go about creating
+ albums and uploading appropriate images as they see fit. They
+ cannot create new subfolders, so the folder structure will not
+ become fragmented and disorganized (the admin is both a control and
+ neat freak).
The admin later realizes that Lap Dogs and Yappy Dogs are
+ basically the same thing so she consolidates the two folders into
+ one called Trouble Dogs.
Since the point of the dog album is to show off various dogs,
+ she wants the world to be able to see them. She grants view access
+ to all albums within her subsite to the general public.
+ A photo is a generic content item for user uploaded photos. Each
+ photo will have image content items associated with it that store
+ the actual binary files and any image specific attributes. Photo
+ and image content items can accommodate multiple revisions.
+
+
VI.A.10 System will store three images associated with a photo:
+ the original image, thumbnail image, and a view-sized image.
VI.A.20 System will maintain a revision history for the photos
+ and record which revision is current for given situation.
VI.A.30 Images shall be stored so that they can be served
+ efficiently. The system should allow for storing the binary files
+ in either the file system or the database. This should be
+ controlled by a parameter. The initial implementation may only
+ support one storage type, but it should be open to either storage
+ type.
VI.A.40 Photos and any revisions have attribute data associated
+ with them. The method and structure for storing these attributes
+ will be decided as part of the design and implementation.
+
+
VI.A.40.10 System specified attributes. Certain attributes will
+ be specified and maintained by the system. These attributes will
+ include: uploading_user, user_filename, original_file_size,
+ original_width, orginal_height, orginal_path, thumb_width,
+ thumb_height, thumb_file_size, thumb_path, view_width, view_height,
+ view_file_size, view_path, caption, upload_date. Other attributes will be
+ determined during the design process.
VI.A.40.20 Administrator specified attributes. The site
+ administrator can specify custom attributes of photos and if these
+ attributes are required/optional for uploaded photos. The initial
+ system will not support admin customized attribute fields. However
+ the system shall be designed so that it is open to adding this in
+ the future.
VI.A.40.30 User Specified Attributes. The initial system will
+ not support user customized attribute fields. However the system
+ shall be designed so that it is open to adding user customized
+ fields in the future.
+
VI.A.50 System shall be open to adding server-backed image
+ manipulation with a future version. This may include image
+ rotation, cropping, and other simple editing. Since image
+ manipulation can be a cpu-intensive process, many users
+ manipulating many images at the same time could potentially slow a
+ sites response time. Any implementation of these feature should
+ support redirecting manipulation requests to an alternate server
+ for processing images to alleviate the load on the main
+ server.
VI.B.10.10 Photos have a distinct order within an album
VI.B.10.20 User with edit privileges can modify/reorder photos
+ within album.
+
VI.B.20 Album has page to display several thumbnail images in
+ an album.
+
+
VI.B.20.10 Number of thumbnails per page is controlled in admin
+ page. Display page must dynamically react to changes on the admin
+ page.
VI.B.20.20 Thumbnail display can scroll through next and
+ previous pages, next / previous page group, or click on page
+ number.
VI.B.20.30 Clicking on thumbnail calls view-size display
+ page.
VI.B.20.40 Attributes can be displayed with thumbnails. Display
+ controlled in admin page or in template page.
+
VI.B.30 Album has page to display single view-size image.
+
+
VI.B.30.10 When viewing one image user can navigate to next and
+ previous photo or return to thumbnail page.
VI.B.30.20 Viewer can display attributes of photo. Display
+ controlled in admin page or in template page.
+
VI.B.40 The display pages should use templates for designating
+ layout and formatting. The templates should be able to accommodate
+ parameter changes made through the admin pages. So if the admin
+ changes the albums from displaying 4 200x200 thumbnails at a time
+ to 6 100x100 thumbnails, the display pages should reformat
+ accordingly with minimal changes to the display templates
VI.B.50 Potential page to display the original images. Such a
+ page would allow the user to view and save the original size
+ high-resolution version of the photo instead of the lower
+ resolution and smaller sized viewer and thumbnail images. Since
+ some sites and admins may not want users to have access to the
+ high-resolution originals, the admin must be able to toggle the
+ availability of such page.
VI.B.60 User with edit privilege can do following:
+
+
VI.B.60.10 Upload new photos to an album and specify attributes
+ during upload process.
VI.B.60.20 Photos can be moved to different albums within same
+ hierarchy.
VI.D.10 Number of thumbnail to be displayed at a time on the
+ page described in VI.B.20 specified in by a sub-site admin. Number
+ of thumbnails pre page can be changed by the admin at any time and
+ display pages react accordingly.
VI.D.20 Thumbnail and view-size specified by sub-site admin.
+
+
VI.D.20.10 Thumbnail and view-size can be changed by
+ sub-site-admin. Two options are allowed for size changes, proactive
+ and retroactive.
+
+
VI.D.20.10.10 Proactive change will only change new photo
+ uploads. Any changes will take affect immediately. Previously
+ uploaded photos will maintain original thumbnail and view-size
+ images until photo is revised.
VI.D.20.10.20 Retroactive changes will change new photo uploads
+ and resize all previously uploaded photos. Since the time to
+ complete such revision will vary with the number of photos
+ uploaded, the system shall provides an estimate of how long it will
+ take and asks if admin wishes to continue. If yes it schedule
+ conversion process to run during low bandwidth times, and provides
+ daily email updates if process will take longer than a day. Also
+ checks for server crashes/restarts that would hinder conversion.
+ (This requirement will be delayed until a future version)
+
+
VI.D.30 Admin can edit other people's albums.
VI.D.40 Admin designates default permissions for hierarchy
+ levels. So various users can view, create, edit, and upload to
+ different levels.
VI.D.50 Admin can allow user to access the page displaying the
+ original size high-resolution version of a photo described in
+ VI.B.50
VI.E.10 Photos uploaded one at a time through an html form.
+ Form shall provide ability to specify attribute information.
VI.E.20 Upload system shall support uploading to separate
+ dedicated server(s). Creating the thumbnail and viewer size images
+ of a photo can be a cpu-intensive process. Many users uploading
+ many photos simultaneously can potentially slow a sites response
+ time. Redirecting upload requests to an alternate server for
+ processing images can lessen the load on the main server.
+ (Implementation of this will be delayed until a future release).
A photo album system was built for the IluvCamp Client site.
+ Much of the work on the ACS 4.0 Photo Album Package will be based
+ on the lessons learned building and maintaining this system. Some
+ of these lessons include:
The ability (and necessity on high volume sites) to support
+ dedicated image processing servers. As outlined in two of the
+ requirements above, numerous simultaneous image manipulations can
+ tie up resources on the main server. Low volume sites may be able
+ to handle image manipulation on the main server, but high volume
+ sites will need the ability to pass these operations off to
+ dedicated servers.
The ability to support a pool of multiple servers. The Iluvcamp
+ site used a pool of multiple servers on several machines to support
+ the high volumes of traffic. Additionally, many attributes of the
+ album structure and hierarchy were cached to improve performance.
+ When we made changes to these attributes that required cache
+ flushes, we needed to make sure the caches were flushed on all the
+ servers.
The Iluvcamp data structure mapped a specific number of images
+ to a page and then mapped the pages to albums. All of this mapping
+ and ordering information was stored in the database. This
+ essentially hard-coded the image on page ordering and the number of
+ images per page. Unfortunately this made changing the display of
+ albums from 9 images per page to 4 images per page (a mid-season
+ client request) time consuming and difficult. Given that the
+ requirements allow for easy changes to the number of thumbnails
+ displayed per page, such hard-coding should be avoided at all cost
+ in the photo album package. Photos should be mapped directly to
+ albums and pages within the album should be rendered
+ dynamically.
The amount of time it takes to retroactively change thumbnail
+ and view-size images. A client requested change of the thumbnail
+ and viewer size images on IluvCamp took several weeks of processor
+ time to modify ~ 240,000 previously uploaded images. Scheduling and
+ monitoring the conversion process was a headache. We hope to figure
+ out a easier way to make such a change.
The Photo Album Package is a generalized application for storing and
+ displaying groups of photos on a web site. It provides a convenient and uniform system
+ for uploading, storing, and displaying groups of photos on a web
+ site. It removes the tedious part of building pages to display
+ photos, and allows users more flexibility to maintain and modify
+ their own photo albums. It also removes much of the burden from the
+ owners/maintainers of the site. All of these factors add up to a
+ system that allows community members to easily contribute and view
+ large amounts of compelling content on a site.
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/doc/release-notes.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/release-notes.html,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/doc/release-notes.html 10 Jun 2003 10:07:46 -0000 1.1
@@ -0,0 +1,215 @@
+
+Release Notes for Photo Album 4.0.1 Final Release
Removed photo level premission checks. Load testing showed
+ that allowing different photos within the same album to have different
+ permissions made the queries to get the photos in a large album very slow.
+ I changed the application logic so that all photos in album have same permission
+ and permission check is done at the album level.
+
Tunned numerous queries base on load testing results
+ against a database filed with 10,000 photos.
+
Made compatible with acs-kernal 4.1.1 and acs-templating 4.1.
+
Added caching of primary keys of photos in an album and package root folder_id.
+
Added optional permission check when serving images.
+
Added separate optional page to display the base sized photo.
+
When uploading a photo, the thumbnail is now created from the
+ viewer sized image rather from the base sized image. Creating a small image
+ from a medium-sized image is much faster than creating a small image from a
+ large image and does not noticably change the image quality.
+
Minor revisions to plsql packages to improve compatability with acs-content-repository.
+
Added more detailed documentation in both html and docbook format.
+
Fixed name conflicts with photo album lite.
+
Besides upgrading the rest of your acs intall to 4.1.1, you will need to mannually run
+ photo-album/sql/plsql-packages.sql through sqlplus to update
+ the packages inside oracle when upgrading from the beta to final version of the photo-album.
\ No newline at end of file
Index: openacs-4/packages/photo-album/www/doc/xml/design.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/xml/design.xml,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/doc/xml/design.xml 10 Jun 2003 10:08:03 -0000 1.1
@@ -0,0 +1,700 @@
+
+ ACS 4 Photo Album Package Design Documentation
+ by Tom Baginski,
+ bags@arsdigita.com
+
+
+
+ Essentials
+
+
+
+ User accessible directory depends on where package is mounted
+ in site.
+
+
+ No separate administration directories
+
+ Tcl procedures: packages/photo-album/tcl/photo-album-procs.tcl
+ (link to proc depends on install)
+
+ Data model: packages/photo-album/sql/photo-album-create.sql
+ (link to data model depends on install)
+
+
+
+
+
+
+
+
+
+
+ Introduction
+
+ The basic content element of the photo album system is a photo.
+ When a user uploads a photo, the system stores attribute
+ data such as caption, story, and title as a
+ single content element. Each photo associated with several
+ (three to start) image elements that store the actual binary files.
+ The image elements, which are created by the server, are standard sized
+ versions of the original photo used for display. Photos and images
+ can have descriptive attributes associated with them. The attributes
+ and binary files can be revised and the system will retain past
+ versions.
+
+ Photos are grouped together into albums which can contain 0 or
+ more photos. The albums can have descriptive attribute information
+ that can be revised with history tracking. The albums can be
+ displayed as a unit that allows user to browse through the photos
+ in the album.
+
+ Albums can be grouped together into folders that can contain 0
+ or more albums or other folders.
+
+ An instance of the package include pages to display the folders,
+ albums, and photos along with admin pages. Instances can be mounted
+ to different subsite and managed independently. The grouping is
+ included within the instance so that the albums maintain a
+ consistent url even if they are re-sorted to different folders
+ within the instance (as long as the subsite url isn't changed).
+
+ The display, grouping, and administration functionality of the
+ photo album package will be included in the initial release of the
+ package. This is intended to be one part of a larger system that
+ will allow bulk uploading and purchasing of photos. These two
+ feature have already been implemented on aD customer sites. ACS 4
+ versions of these features will be either incorporated into a
+ future version of the photo album package or added as individual
+ packages that depend on the photo album.
+
+ The basic tasks of the photo album revolve around storing and
+ displaying content and associated attributes. As such, this package
+ will take advantage of the exiting features of the content
+ repository service package. The content repository can store
+ multiple revisions of content items such as photos and images and
+ their associated attributes. The content repository also provides
+ grouping functions. The acs permission service will be used for
+ access control so view, edit, and administration privileges will be
+ highly customizable. Finally individual photo album instances can
+ be added to subsites to support multiple independent photo albums
+ on the same site.
+
+
+
+ Historical Considerations
+
+ The the development of photo album package was base largely on
+ the experience of building a custom photo album application for the
+ Iluvcamp client site. The Iluvcamp photo album was built using an
+ early version of the content repository. The photo album package
+ uses the current version of the ACS content repository and takes
+ advantage of several key features of the ACS4 structure such as
+ permissions, templating, the content repository. The photo album
+ package avoid several of the limitation of the Iluvcamp Photo Album
+ that were made clear after supporting a summer of use and uploading
+ over 70GB of original photos.
+
+ A photodb application was developed for ACS 3.x. The option of
+ porting the photodb application to ACS4 was not followed due to the
+ customized nature of the photodb application. It was primarily
+ designed for storing and displaying information about photos for
+ photographers. In contrast, the photo album application provides a
+ general system for storing and displaying user uploaded photos,
+ which can be customized to any particular client application.
+
+
+
+ Competitive Analysis
+
+ Not done. A google search for "photo album web application"
+ returns links for several shareware photo album applications.
+ I did not install or test any of these.
+
+
+
+ Design Tradeoffs
+
+ The package uses/requires the convert and identify
+ ImageMagick
+ binaries to be installed on the host computer at the location
+ specified in the ImageMagickPath parameter. ImageMagick is readily
+ available and easy to use from within server pages. ImageMagick is
+ copyrighted by ImageMagick Studio, a nonprofit organization.
+ ImageMagick is available for free, may be used to support both open
+ and proprietary applications, and may be redistributed without fee.
+ The previous ImageMagick Homepage has some mention of LZW patent
+ issues and redirects to a new location. If these patent issues
+ become a problem, the package will need to be re-coded to use
+ different image manipulation software.
+
+ By default the package stores the image binary files in the file
+ system. This decision was made for ease of use and development.
+ This was also based on the assumption that file system storage is
+ more appropriate for large systems with many giga-bytes of photos.
+ The content repository also provides support for database storage
+ of binaries in blobs. Future version of the photo album will also
+ support database storage of photos. Load testing will be used to
+ determine the most appropriate storage method for small and large
+ volumes of photos.
+
+ The default photo storage directory is outside of the page root
+ and images are served using a .vuh file. This was done to prevent
+ potential execution of user uploaded files. Although the package
+ checks that the user only uploads image files, in theory a rouge
+ user could upload a code file. If that file was directly accessible
+ from the page root, the rouge user could execute arbitrary code
+ with all the authority of the web server user. Serving the image
+ through a .vuh file also allows for checking access permissions to
+ a file before it is served to the user. The benefits of serving
+ image files with a .vuh file comes at a cost of some additional
+ server resources. Again, load testing will be used to determine the
+ true cost of using a .vuh file.
+
+ The photo attribute information and binary files are stored in
+ two different content types (pa_photos and pa_images). The linkage
+ between the binaries and the attribute info is maintained as a
+ relationship between the two content_items. This decision was made
+ so the the number of image sizes per photo could be changed with minor
+ code revision and no datamodel changes. This flexibility comes at a
+ cost, the queries to retreive and serve the appropriate version of
+ a photo need to join in several tables to do so. There also is not
+ an easy way to store the relation between different versions of the
+ photo-attribute info such as caption and the versions of the binaries.
+
+
+
+ API
+
+
+ PL/SQL API
+
+ The PL/SQL database api is incorporated into four packages: pa_image,
+ pa_photo, pa_album, and photo_album. The first three correspond to the
+ 3 new object types created for the photo album application. The last
+ contains general database functions for the application.
+
+
+ pa_image package
+
+
+ pa_image.new creates a new pa_image object type and returns the
+ cr_item.item_id of the newly created object. It also create the first revision
+ of that object. It accepts an item_id and revision_id as arguments but both
+ will be created if not provided. Although relation tag defaults to null it
+ should be in (thumb, viewer, base). Path is the path to the image binary relative
+ to the upload base (a parameterized directory).
+
+ function new (
+ name in cr_items.name%TYPE,
+ parent_id in cr_items.parent_id%TYPE default null,
+ item_id in acs_objects.object_id%TYPE default null,
+ revision_id in acs_objects.object_id%TYPE default null,
+ content_type in acs_object_types.object_type%TYPE default 'pa_image',
+ creation_date in acs_objects.creation_date%TYPE default sysdate,
+ creation_user in acs_objects.creation_user%TYPE default null,
+ creation_ip in acs_objects.creation_ip%TYPE default null,
+ locale in cr_items.locale%TYPE default null,
+ context_id in acs_objects.context_id%TYPE default null,
+ title in cr_revisions.title%TYPE default null,
+ description in cr_revisions.description%TYPE default null,
+ mime_type in cr_revisions.mime_type%TYPE default null,
+ nls_language in cr_revisions.nls_language%TYPE default null,
+ relation_tag in cr_child_rels.relation_tag%TYPE default null,
+ is_live in char default 'f',
+ publish_date in cr_revisions.publish_date%TYPE default sysdate,
+ path in pa_images.path%TYPE,
+ height in pa_images.height%TYPE default null,
+ width in pa_images.width%TYPE default null,
+ file_size in pa_images.file_size%TYPE default null
+ ) return cr_items.item_id%TYPE;
+
+
+
+ pa_image.delte_revision deletes a specified revision
+ of a pa_image and schedules the binary for deleation from the file-system by a sweep procedure
+
+
+
+ procedure delete_revision (
+ revision_id in cr_revisions.revision_id%TYPE
+ );
+
+
+ pa_image.delete deletes a pa_image and all revisions
+ Also schedules the binary files for deletion from the file-sytem.
+
+
+ procedure delete (
+ item_id in cr_items.item_id%TYPE
+ );
+
+
+
+
+ pa_photo package
+
+
+ pa_photo.new create a new pa_photo object
+ and returns the cr_item.item_id of the new object. Also creates first revision of object
+
+
+ function new (
+ name in cr_items.name%TYPE,
+ parent_id in cr_items.parent_id%TYPE default null,
+ item_id in acs_objects.object_id%TYPE default null,
+ revision_id in acs_objects.object_id%TYPE default null,
+ content_type in acs_object_types.object_type%TYPE default 'pa_photo',
+ creation_date in acs_objects.creation_date%TYPE default sysdate,
+ creation_user in acs_objects.creation_user%TYPE default null,
+ creation_ip in acs_objects.creation_ip%TYPE default null,
+ locale in cr_items.locale%TYPE default null,
+ context_id in acs_objects.context_id%TYPE default null,
+ title in cr_revisions.title%TYPE default null,
+ description in cr_revisions.description%TYPE default null,
+ relation_tag in cr_child_rels.relation_tag%TYPE default null,
+ is_live in char default 'f',
+ publish_date in cr_revisions.publish_date%TYPE default sysdate,
+ mime_type in cr_revisions.mime_type%TYPE default null,
+ nls_language in cr_revisions.nls_language%TYPE default null,
+ caption in pa_photos.caption%TYPE default null,
+ story in pa_photos.story%TYPE default null,
+ user_filename in pa_photos.user_filename%TYPE default null
+ ) return cr_items.item_id%TYPE;
+
+
+ pa_photo.delete_revision deletes a specified
+ revision of a pa_photo
+
+
+ procedure delete_revision (
+ revision_id in acs_objects.object_id%TYPE
+ );
+
+
+ pa_photo.delete deletes a pa_photo object,
+ all revision of a pa_photo, and all associated pa_images (including binaries). Basically nukes
+ a photo, so be careful using this one, because it can't be undone.
+
+
+ procedure delete (
+ item_id in acs_objects.object_id%TYPE
+ );
+
+
+
+
+
+ pa_album package
+
+
+ pa_album.new creates a new pa_album object type and returns the
+ cr_item.item_id of the newly created object. It also create the first revision
+ of that object. It accepts an item_id and revision_id as arguments but both
+ will be created if not provided.
+
+ function new (
+ name in cr_items.name%TYPE,
+ album_id in cr_items.item_id%TYPE default null,
+ parent_id in cr_items.parent_id%TYPE default null,
+ revision_id in cr_revisions.revision_id%TYPE default null,
+ content_type in acs_object_types.object_type%TYPE default 'pa_album',
+ is_live in char default 'f',
+ creation_date in acs_objects.creation_date%TYPE default sysdate,
+ creation_user in acs_objects.creation_user%TYPE default null,
+ creation_ip in acs_objects.creation_ip%TYPE default null,
+ locale in cr_items.locale%TYPE default null,
+ context_id in acs_objects.context_id%TYPE default null,
+ relation_tag in cr_child_rels.relation_tag%TYPE default null,
+ publish_date in cr_revisions.publish_date%TYPE default sysdate,
+ mime_type in cr_revisions.mime_type%TYPE default null,
+ nls_language in cr_revisions.nls_language%TYPE default null,
+ title in cr_revisions.title%TYPE default null,
+ description in cr_revisions.description%TYPE default null,
+ story in pa_albums.story%TYPE default null
+ ) return cr_items.item_id%TYPE;
+
+
+ pa_album.delte_revision deletes a specified revision
+ of a pa_album
+
+
+ procedure delete_revision (
+ revision_id in cr_revisions.revision_id%TYPE
+ );
+
+
+ pa_album.delete deletes a pa_album and all revisions
+ of that album. The album must not have any child pa_phots or the delete throws an error. So
+ there is nothing equilent to rm -r *. You separately delete the
+ photos in an album (or move them to a different album) then delete the album.
+
+
+ procedure delete (
+ album_id in cr_items.item_id%TYPE
+ );
+
+
+
+
+ photo_album package
+
+
+ photo_album.get_root_folder returns the root folder
+ for a given package_id (package instance). The root folder for a package is actually cached by the
+ web server. So it is probably faster to call the server proc pa_get_root_folder and pass the value
+ in as a bind variable any place you need the root_folder in a query.
+
+
+ function get_root_folder (
+ package_id in apm_packages.package_id%TYPE
+ ) return pa_package_root_folder_map.folder_id%TYPE;
+
+
+
+
+
+
+
+
+
+ Procedural API
+
+ The public procedural API available from the webserver is currently
+ implemented as tcl procedures.
+
+
+ pa_get_root_folder {package_id ""}
+ Returns the folder_id of the root folder for an instance of the photo album system.
+ If no root folder exists, as when a new package instance is accessed for the first time,
+ a new root folder is created automatically with appropriate permissions
+ If value has be previously requested, value pulled from cache. If pakage_id is not specified,
+ procedure uses value from [ad_conn package_id]
+
+
+ pa_context_bar_list {-final ""} item_id
+ Constructs the list to be fed to ad_context_bar appropriate for
+ item_id. If -final is specified, that string will be the last
+ item in the context bar. Otherwise, the name corresponding to
+ item_id will be used.
+
+
+ pa_make_file_name {-assert:boolean} {-ext ""} id
+ Constructs a filename for an image based on id and extention.
+ Files are created into a 3 tier directory structure: year/xx/zz/ for a photo_id 1234xxzz.jpg
+ Same file would return year/xx/zz/1234xxzz.jpg.
+ If -assert specified, proc creates directory and any parent directories if necessary
+
+
+ pa_is_folder_p folder_id {package_id ""}
+ Returns "t" if folder_id is a folder that is a child of the root folder for the package,
+ else "f". If package_id is not given procedure uses value from
+ [ad_conn package_id].
+
+
+ pa_is_album_p album_id {package_id ""}
+ Returns "t" if album_id is a album that is a child of the root folder for the package,
+ else "f" If package_id is not given procedure uses value from
+ [ad_conn package_id].
+
+
+ pa_is_photo_p photo_id {package_id ""}
+ Returns "t" if photo_id is a photo that is a child of the root folder for the package,
+ else "f" If package_id is not given procedure uses value from
+ [ad_conn package_id].
+
+
+ pa_grant_privilege_to_creator object_id {user_id ""}
+ Grants a set of default privileges stored in parameter PrivilegeForCreator
+ on object id to user_id. If user_id is not specified, uses current user.
+
+
+ pa_image_width_height filename width_var height_var
+ Uses ImageMagick program to get the width and height in pixels of filename.
+ Sets height to the variable named in height_var in the calling level.
+ Sets width_var to the variable named in width_var in the calling level.
+
+ I Use ImageMagick instead of aolsever funcition because it can handle more than
+ just gifs and jpegs.
+
+
+ pa_make_new_image base_image new_image max_width {max_height ""}
+ Uses ImageMagick program to create a file named new_image from base_image that
+ fits within a box defined by max_width by max_height (in pixels).
+ ImageMagick will retain the aspect ratio of the base_image when creating the new_image
+ If max_height is not specified, max_width is used for max_height.
+
+
+ pa_all_photos_in_album album_id
+ Returns a list of all the photo_ids in an album sorted in ascending order.
+ Pulls value from cache if already there, caches result and returns result if not
+
+
+ pa_count_photos_in_album album_id
+ Returns count of number of photos in album_id
+
+
+ pa_all_photos_on_page album_id page
+ Returns a list of the photo_ids on page page of album_id.
+ List is in ascending order
+
+
+ pa_count_pages_in_album album_id
+ Returns the number of pages in album_id
+
+
+ pa_page_of_photo_in_album photo_id album_id
+ Returns the page number of a photo in an album. If photo is not in the album returns -1
+
+
+ pa_flush_photo_in_album_cache album_id
+ Clears the cacheed value set by pa_all_photos_in_album for a single album
+ Call proc on any page that alters the number or order of photos in an album.
+
+
+ pa_pagination_page_number_links page total_pages
+ Returns html table fragament for navigating pages of an album.
+
+
+ pa_photo_number_links cur_id all_ids
+ Given a current photo_id and and an ordered list of all the photo_id in an album,
+ creates an html fragment that allows user to navigate to any photo by number,
+ or next/previous. Pulls url from connection so should work on page showing a single photo
+ based on photo_id (such as viewer size display page or base size display page).
+
+
+
+
+
+
+
+
+
+ Data Model Discussion
+
+ The data model defines 3 new content types within the content
+ repository. These are pa_album, pa_photo, and pa_image. It uses the
+ exiting content_folder for grouping pa_albums. Pa_albums store
+ attribute information about a group of photos and serves as a
+ container for 0 or more photos. Pa_photos store attributes of user uploaded
+ photo. Pa_images are used as a helper type to store the base (original),
+ thumbnail and viewer display images associated
+ with a pa_photo. Each pa_photo has one child pa_image for its
+ base photo, one for its thumbnail image, and one child pa_image for its viewer image. The
+ pa_images are created by the server whenever a pa_photo is added
+ or edited.
+
+ The root folder for each package instance is stored in pa_root_folder_package_map.
+ All folders, albums, photos, and images within a package instance are
+ decendants of the root folder for that package.
+
+ Image files scheduled for deletion are stored in pa_files_to_delete. A
+ nightly web-server process deletes the files in this table and then removes
+ them from the table. This table allows images to be deleted transactionally from
+ both the database and the file-system. All photo/image delete operations should
+ add the binary file-name to pa_files_to_delete and then delete the attribute information
+ in the database within a transaction. This way the file system delete will not
+ happen unless the database delete succeeds.
+
+
+
+
+ User Interface
+
+ The user accessible pages contain a set of pages for displaying,
+ adding, and editing folders, albums, and photos. The folder page
+ which serves as the index page allows a user to navigate to
+ sub-folders and albums within the folder. The album page displays
+ the photos (or a sub-set of photos) within an album. The photo page
+ displays a single photo.
+
+
+
+ Configuration/Parameters
+
+ Parameters are set by default through the apm and can be
+ edited by a user with admin privileges for a sub-site through the
+ current sub-site admin pages. Depending on which version of the
+ apm is installed, the server may need to be restarted for
+ the parameters of a new package instance are available.
+
+ The defined parameters are as follows:
+
+
+ ImageMagickPath
+
+ Description: Absolute path from computer root to directory
+ containing ImageMagick executables convert and identify.
+ Default: /usr/local/bin
+
+
+ PhotoDir
+
+ Description: Relative path from acs_root_dir to directory for
+ storing uploaded images. (do not include leading or trailing
+ forward slash)
+ Default: uploaded-photos
+
+
+ FullTempDir
+
+ Description: Absolute path from computer root to path for
+ temporary photos.
+ Default: /tmp/photo-album
+
+
+ PhotoStorageMethod
+
+ Description: Default method for storing photos, file-system or
+ database. (Package currently only supports file-system)
+ Default: file-system
+
+
+ ThumbnailSize
+
+ Description: Max Dimension for thumbnail image
+ Default: 100
+
+
+ ViewerSize
+
+ Description: Max Dimension for viewer images
+ Default: 400
+
+
+ ThumbnailsPerPage
+
+ Description: Number of thumbnail images to be displayed per album
+ page
+ Default: 12
+
+
+ PrivilegeForCreator
+
+ Description: CSV of privileges to grant to creators of new objects
+ within photo album
+ Default: admin
+
+
+ AcceptableUploadMIMETypes
+
+ Description: CSV of acceptable MIME Types for Photo Upload
+ Default: image/jpeg,image/gif
+
+
+ DefaultRootFolderPrivileges
+
+ Description: List of grantee privilege pairs for new root folders.
+ Grantee is an integer or function that returns a party_id. Format
+ as a space separated list
+ Default: acs.magic_object_id('the_public') read
+ acs.magic_object_id('registered_users') pa_create_album
+ acs.magic_object_id('registered_users') pa_create_folder
+
+
+ AllowBasePhotoAccessP
+
+ Description: If set to "t", users are presented a link to
+ display the full sized base image from photo page.
+ Default: t
+
+
+ CheckPermissionOnImageServeP
+
+ If set to "t", the images/index.vuh file runs a query to check
+ if user has read access to photo prior to serving it. Note, setting to
+ "t" can impact performance on high volume sites. The urls for images
+ also change depending on this parameter. If "t" url contains the
+ pa_image_id, else contains the path to the pa_image in file-system.
+ Default: f
+
+
+
+
+
+
+ Future Improvements/Areas of Likely Change
+
+
+ Server backed image manipulation
+
+ Purchase and printing of photo through ecommerce package and
+ photo printing vendor.
+
+ Bulk upload tool
+
+ User specified attributes
+
+ Upload quotas
+
+ Admin notification of file space limitations.
+
+ Search and retrieval of photos and albums based on attributes
+ or key words.
+
+ Admin specified attributes
+
+
+
+
+ Authors
+
+
+ System creator, System owner, and Documentation author: Tom
+ Baginski, bags@arsdigita.com
+
+
+
+
+ Revision History
+
+
+
+
+
+ Document Revision #
+
+ Action Taken, Notes
+ When?
+ By Whom?
+
+
+
+
+
+ 0.1
+ Creation
+ 12/17/2000
+ Tom Baginski
+
+
+
+ 0.2
+ Editing
+ 1/9/2001
+ Tom Baginski
+
+
+
+ 0.3
+ Editing and additions to API and Data Model sections.
+ 2/5/2001
+ Tom Baginski
+
+
+
+
+
+
+ bags@arsdigita.com
+
+
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/doc/xml/index.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/xml/index.xml,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/doc/xml/index.xml 10 Jun 2003 10:08:03 -0000 1.1
@@ -0,0 +1,133 @@
+
+
+
+]>
+
+
+ Photo Album
+
+
+
+ Tom
+ Baginski
+
+ bags@arsdigita.com
+
+
+
+
+
+
+ Introduction
+ The Photo Album Package is a generalized application for storing and
+ displaying groups of photos on a web site. It provides a convenient and uniform system
+ for uploading, storing, and displaying groups of photos on a web
+ site. It removes the tedious part of building pages to display
+ photos, and allows users more flexibility to maintain and modify
+ their own photo albums. It also removes much of the burden from the
+ owners/maintainers of the site. All of these factors add up to a
+ system that allows community members to easily contribute and view
+ large amounts of compelling content on a site.
+
+
+
+
+ Release Notes for Photo Album 4.0.1 Final Release
+ Changes from 4.0.1 beta to 4.0.1 final.
+
+
+ Removed photo level premission checks. Load testing showed
+ that allowing different photos within the same album to have different
+ permissions made the queries to get the photos in a large album very slow.
+ I changed the application logic so that all photos in album have same permission
+ and permission check is done at the album level.
+
+
+ Tunned numerous queries base on load testing results
+ against a database filed with 10,000 photos.
+
+
+ Made compatible with acs-kernal 4.1.1 and acs-templating 4.1.
+
+
+ Added caching of primary keys of photos in an album and package root folder_id.
+
+
+ Added optional permission check when serving images.
+
+
+ Added separate optional page to display the base sized photo.
+
+
+ When uploading a photo, the thumbnail is now created from the
+ viewer sized image rather from the base sized image. Creating a small image
+ from a medium-sized image is much faster than creating a small image from a
+ large image and does not noticably change the image quality.
+
+
+ Minor revisions to plsql packages to improve compatability with acs-content-repository.
+
+
+ Added more detailed documentation in both html and docbook format.
+
+
+ Fixed name conflicts with photo album lite.
+
+
+
+
+ Besides upgrading the rest of your acs intall to 4.1.1, you will need to mannually run
+ photo-album/sql/plsql-packages.sql through sqlplus to update
+ the packages inside oracle when upgrading from the beta to final version of the photo-album.
+
+
+
+
+
+ ACS Administration Guide
+ Installation and Operation Notes
+
+
+ Imagemagick The convert and identify
+ binaries must be installed within the location specified by the parameter
+ ImageMagickPath. The user that the webserver is running under must have
+ execute privileges for the files. A link to a download page for ImageMagick
+ can be found in the design document.
+
+
+ Image Storage Directory The photo album
+ store image binaries in the file system. The webserver user must have read,
+ write, and execute privileges for the directory specified in the parameter PhotoDir.
+ This directory must be in the acs root directory for the server. The webserver
+ user must also have write privilege on any file created in this directory or it
+ will not be able to delete images.
+
+
+ Permission Checks for Serving Images The parameter
+ CheckPermissionOnImageServeP controls if images/index.vuh queries the database to
+ check if user has read permission on a photo prior to serving it. Setting this to true
+ will slow server performance because it causes an extra trip to the database for every
+ image served. Default album pages serve 12 thumbnails per page, which translates into 12
+ extra trips to the database. Users should not be presented a link/img tag for an image
+ for which they do not have read privileges. Unless you are really concerned about someone
+ url hacking to a private image (which they would need to know the full path), I suggest
+ leaving this parameter set to false.
+
+
+
+
+
+
+
+
+
+ Developer's guide
+ &requirements;
+ &design;
+
+
+
+
Index: openacs-4/packages/photo-album/www/doc/xml/requirements.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/xml/requirements.xml,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/doc/xml/requirements.xml 10 Jun 2003 10:08:03 -0000 1.1
@@ -0,0 +1,608 @@
+
+
+
+ ACS 4.0 Photo Album Application Requirements
+
+
+ by Tom Baginski,
+ bags@arsdigita.com
+
+
+
+ Introduction
+
+ This document presents the requirements for the ACS 4.0 Photo
+ Album Package, which is a generalized application for storing and
+ displaying groups of photos on a web site. It is intended to build
+ on the experience gained from creating and maintaining a photo
+ album system for the IluvCamp client site.
+
+
+
+ Vision Statement
+
+ Many people want to display photos on the web. Building a simple
+ personal web page with vacation photos is easy and can be done by
+ hand with static html. Building 100 similar web pages for all your
+ friends and relatives would be tedious. More importantly it would
+ be difficult to maintain and scale such a system to support all the
+ users of a large site.
+
+ The photo album package provides a convenient and uniform system
+ for uploading, storing, and displaying groups of photos on a web
+ site. It removes the tedious part of building pages to display
+ photos, and allows users more flexibility to maintain and modify
+ their own photo albums. It also removes much of the burden from the
+ owners/maintainers of the site. All of these factors add up to a
+ system that allows community members to easily contribute and view
+ large amounts of compelling content on a site.
+
+ The initial version of the package will allow designated users
+ to upload photos into albums and to group albums into a folder
+ hierarchy that other users with appropriate permissions can view
+ and possibly edit.
+
+ Future improvement to the photo album package will incorporate
+ additional features developed on various customer sites that allow
+ users to upload photos in bulk through a client applet and to
+ purchase prints of photos presented on the site.
+
+
+
+ System/Application Overview
+
+ The basic content element of the photo album system is a photo.
+ When a user uploads a photo, the system stores attribute
+ data such as caption, story, and title as a
+ single content element. Each photo associated with several
+ (three to start) image elements that store the actual binary files.
+ The image elements, which are created by the server, are standard sized
+ versions of the original photo used for display. Photos and images
+ can have descriptive attributes associated with them. The attributes
+ and binary files can be revised and the system will retain past
+ versions.
+
+ Photos are grouped together into albums which can contain 0 or
+ more photos. The albums can have descriptive attribute information
+ that can be revised with history tracking. The albums can be
+ displayed as a unit that allows user to browse through the photos
+ in the album.
+
+ Albums can be grouped together into folders that can contain 0
+ or more albums or other folders.
+
+ An instance of the package include pages to display the folders,
+ albums, and photos along with admin pages. Instances can be mounted
+ to different subsite and managed independently. The grouping is
+ included within the instance so that the albums maintain a
+ consistent url even if they are re-sorted to different folders
+ within the instance (as long as the subsite url isn't changed).
+
+ The display, grouping, and administration functionality of the
+ photo album package will be included in the initial release of the
+ package. This is intended to be one part of a larger system that
+ will allow bulk uploading and purchasing of photos. These two
+ feature have already been implemented on aD customer sites. ACS 4
+ versions of these features will be either incorporated into a
+ future version of the photo album package or added as individual
+ packages that depend on the photo album.
+
+ The basic tasks of the photo album revolve around storing and
+ displaying content and associated attributes. As such, this package
+ will take advantage of the exiting features of the content
+ repository service package. The content repository can store
+ multiple revisions of content items such as photos and images and
+ their associated attributes. The content repository also provides
+ grouping functions. The acs permission service will be used for
+ access control so view, edit, and administration privileges will be
+ highly customizable. Finally individual photo album instances can
+ be added to subsites to support multiple independent photo albums
+ on the same site.
+
+
+
+ Use-cases and User-scenarios
+
+
+ General Scenarios
+
+
+ A young couple just got married. His family shot 20 rolls of
+ film at the wedding and the photographer they hired shot an
+ additional 15 rolls. Now that the wedding is over, this couple must
+ organize their photos. In addition to creating traditional,
+ physical photo albums, they want to publish their photos on the web
+ to share with friends and family all over the world.
+
+ The couple scans the images they want to publish on the web.
+ Most of the images were scanned from the negatives at processing
+ time making it easy for the couple to obtain digital versions of
+ their photographs. The couple creates a new photo album for their
+ wedding, and then adds the following folders: "Engagement photo
+ shoot," "Rehearsal dinner," "Ceremony," "Reception," and
+ "Honeymoon." The honeymoon itself was spent in two different
+ places. The couple creates subfolders for each of these places in
+ their Honeymoon folder.
+
+ Now the folder hierarchy looks like:
+
+
+- Wedding
+ - Engagement Photo Shoot
+ - Rehearsal Dinner
+ - Ceremony
+ - Reception
+ - Honeymoon
+ - Fiji - Big Island
+ - Fiji - Tokoriki
+
+
+ The couple now opens a folder, and uploads images. With each
+ image, the couple can specify optional attributes such as the
+ caption for the photo, the story behind the photo, and an
+ identifier to help them locate the physical negatives at a later
+ date.
+
+ Once the images are uploaded, the couple decides to give their
+ parents administrative access to a couple folders. Now their
+ parents can upload additional photos to those folders or modify the
+ attributes of any given photo.
+
+
+
+
+ The administrator of the "Dogs of the World" subsite on the
+ "All Furry Creatures" web sites wants to provide a way to show
+ pictures of various dog breads. Since the admin is a busy person
+ she doesn't want to upload and manage all of the images herself.
+ She does, however, want to specify the general layout of the
+ various albums and control who can upload images.
+
+ She creates an instance of the photo album within her subsite.
+ Then goes about creating a folder structure such as:
+
+
+- Dogs of the World
+ -Hunting Dogs
+ -Show Dogs
+ -Lap Dogs
+ -Yappy Dogs
+ -Mutts(The coolest)
+
+
+ She then designates certain users or groups of users that she
+ trusts to manage a given folder and grants them permission to
+ create albums within each folder. These users go about creating
+ albums and uploading appropriate images as they see fit. They
+ cannot create new subfolders, so the folder structure will not
+ become fragmented and disorganized (the admin is both a control and
+ neat freak).
+
+ The admin later realizes that Lap Dogs and Yappy Dogs are
+ basically the same thing so she consolidates the two folders into
+ one called Trouble Dogs.
+
+ Since the point of the dog album is to show off various dogs,
+ she wants the world to be able to see them. She grants view access
+ to all albums within her subsite to the general public.
+
+
+
+
+
+
+ Related Links
+
+
+ System/Package "coversheet"
+
+
+
+
+
+ User's guide
+
+ Test plan
+
+ IluvCamp
+ photo albums (Call or email me for log in information)
+
+ Competitive system(s)
+
+
+ Ophoto
+
+ PhotoAccess
+
+ Zing, note zing's photo albums
+ crashed my netscape browser on Linux
+
+ ShutterFly
+
+
+
+
+
+
+ Requirements
+
+
+ Photo Requirements
+
+ A photo is a generic content item for user uploaded photos. Each
+ photo will have image content items associated with it that store
+ the actual binary files and any image specific attributes. Photo
+ and image content items can accommodate multiple revisions.
+
+
+ VI.A.10 System will store three images associated with a photo:
+ the original image, thumbnail image, and a view-sized image.
+
+ VI.A.20 System will maintain a revision history for the photos
+ and record which revision is current for given situation.
+
+ VI.A.30 Images shall be stored so that they can be served
+ efficiently. The system should allow for storing the binary files
+ in either the file system or the database. This should be
+ controlled by a parameter. The initial implementation may only
+ support one storage type, but it should be open to either storage
+ type.
+
+ VI.A.40 Photos and any revisions have attribute data associated
+ with them. The method and structure for storing these attributes
+ will be decided as part of the design and implementation.
+
+
+ VI.A.40.10 System specified attributes. Certain attributes will
+ be specified and maintained by the system. These attributes will
+ include: uploading_user, user_filename, original_file_size,
+ original_width, orginal_height, orginal_path, thumb_width,
+ thumb_height, thumb_file_size, thumb_path, view_width, view_height,
+ view_file_size, view_path, caption, upload_date. Other attributes will be
+ determined during the design process.
+
+ VI.A.40.20 Administrator specified attributes. The site
+ administrator can specify custom attributes of photos and if these
+ attributes are required/optional for uploaded photos. The initial
+ system will not support admin customized attribute fields. However
+ the system shall be designed so that it is open to adding this in
+ the future.
+
+ VI.A.40.30 User Specified Attributes. The initial system will
+ not support user customized attribute fields. However the system
+ shall be designed so that it is open to adding user customized
+ fields in the future.
+
+
+
+ VI.A.50 System shall be open to adding server-backed image
+ manipulation with a future version. This may include image
+ rotation, cropping, and other simple editing. Since image
+ manipulation can be a cpu-intensive process, many users
+ manipulating many images at the same time could potentially slow a
+ sites response time. Any implementation of these feature should
+ support redirecting manipulation requests to an alternate server
+ for processing images to alleviate the load on the main
+ server.
+
+
+
+
+ Album Requirements
+
+
+ VI.B.10 Album is a group of 0 or more photos.
+
+
+ VI.B.10.10 Photos have a distinct order within an album
+
+ VI.B.10.20 User with edit privileges can modify/reorder photos
+ within album.
+
+
+
+ VI.B.20 Album has page to display several thumbnail images in
+ an album.
+
+
+ VI.B.20.10 Number of thumbnails per page is controlled in admin
+ page. Display page must dynamically react to changes on the admin
+ page.
+
+ VI.B.20.20 Thumbnail display can scroll through next and
+ previous pages, next / previous page group, or click on page
+ number.
+
+ VI.B.20.30 Clicking on thumbnail calls view-size display
+ page.
+
+ VI.B.20.40 Attributes can be displayed with thumbnails. Display
+ controlled in admin page or in template page.
+
+
+
+ VI.B.30 Album has page to display single view-size image.
+
+
+ VI.B.30.10 When viewing one image user can navigate to next and
+ previous photo or return to thumbnail page.
+
+ VI.B.30.20 Viewer can display attributes of photo. Display
+ controlled in admin page or in template page.
+
+
+
+ VI.B.40 The display pages should use templates for designating
+ layout and formatting. The templates should be able to accommodate
+ parameter changes made through the admin pages. So if the admin
+ changes the albums from displaying 4 200x200 thumbnails at a time
+ to 6 100x100 thumbnails, the display pages should reformat
+ accordingly with minimal changes to the display templates
+
+ VI.B.50 Potential page to display the original images. Such a
+ page would allow the user to view and save the original size
+ high-resolution version of the photo instead of the lower
+ resolution and smaller sized viewer and thumbnail images. Since
+ some sites and admins may not want users to have access to the
+ high-resolution originals, the admin must be able to toggle the
+ availability of such page.
+
+ VI.B.60 User with edit privilege can do following:
+
+
+ VI.B.60.10 Upload new photos to an album and specify attributes
+ during upload process.
+
+ VI.B.60.20 Photos can be moved to different albums within same
+ hierarchy.
+
+ VI.B.60.30 Photos can be deleted from an album.
+
+ VI.B.60.40 Edit photo attribute information
+
+
+
+
+
+
+ Album Hierarchy
+
+
+ VI.C.10 Albums can be grouped in a hierarchy of arbitrary
+ depth.
+
+ VI.C.20 Display/sorting of hierarchy controlled on the page
+ level but order field included to support arbitrary sorting.
+
+ VI.C.30 Admin (exact permission required, to be determined) can
+ add/consolidate hierarchy levels.
+
+ VI.C.40 Admin (exact permission required, to be determined) can
+ move items around in hierarchy.
+
+ VI.C.50 Admin (exact permission required, to be determined) can
+ resrict the creation of new heirarchy levels.
+
+
+
+
+ Administrative Control
+
+
+ VI.D.10 Number of thumbnail to be displayed at a time on the
+ page described in VI.B.20 specified in by a sub-site admin. Number
+ of thumbnails pre page can be changed by the admin at any time and
+ display pages react accordingly.
+
+ VI.D.20 Thumbnail and view-size specified by sub-site admin.
+
+
+ VI.D.20.10 Thumbnail and view-size can be changed by
+ sub-site-admin. Two options are allowed for size changes, proactive
+ and retroactive.
+
+
+ VI.D.20.10.10 Proactive change will only change new photo
+ uploads. Any changes will take affect immediately. Previously
+ uploaded photos will maintain original thumbnail and view-size
+ images until photo is revised.
+
+ VI.D.20.10.20 Retroactive changes will change new photo uploads
+ and resize all previously uploaded photos. Since the time to
+ complete such revision will vary with the number of photos
+ uploaded, the system shall provides an estimate of how long it will
+ take and asks if admin wishes to continue. If yes it schedule
+ conversion process to run during low bandwidth times, and provides
+ daily email updates if process will take longer than a day. Also
+ checks for server crashes/restarts that would hinder conversion.
+ (This requirement will be delayed until a future version)
+
+
+
+
+
+ VI.D.30 Admin can edit other people's albums.
+
+ VI.D.40 Admin designates default permissions for hierarchy
+ levels. So various users can view, create, edit, and upload to
+ different levels.
+
+ VI.D.50 Admin can allow user to access the page displaying the
+ original size high-resolution version of a photo described in
+ VI.B.50
+
+
+
+
+ Photo Upload
+
+
+ VI.E.10 Photos uploaded one at a time through an html form.
+ Form shall provide ability to specify attribute information.
+
+ VI.E.20 Upload system shall support uploading to separate
+ dedicated server(s). Creating the thumbnail and viewer size images
+ of a photo can be a cpu-intensive process. Many users uploading
+ many photos simultaneously can potentially slow a sites response
+ time. Redirecting upload requests to an alternate server for
+ processing images can lessen the load on the main server.
+ (Implementation of this will be delayed until a future release).
+
+ VI.E.30 Future version to support bulk upload.
+
+
+
+
+ General Requirements
+
+
+ VI.F.10 System to support sub-sites. Admin shall be able to add
+ album implementation to multiple sub-sites on a web service.
+
+ VI.F.20 System shall be able to scale to at least the service
+ level experienced by IluvCamp during summer 2000.
+
+ VI.F.30 Design to accommodate future integration of photo print
+ and purchase capabilities as demonstrated on the IluvCamp Client
+ sites.
+
+
+
+
+ Requirements delayed until future version
+
+
+ VI.G.10 Purchase and printing of photo through ecommerce
+ package and photo printing vendor.
+
+ VI.G.20 Server backed image manipulation
+
+ VI.G.30 Bulk upload tool
+
+ VI.G.40 User specified attributes
+
+ VI.G.50 Upload quotas
+
+ VI.G.60 Admin notification of file space limitations.
+
+ VI.G.70 Search and retrieval of photos and albums based on
+ attributes or key words.
+
+ VI.G.80 Admin specified attributes
+
+ VI.G.90 Photo upload/manipulaion support for separate server.
+
+
+
+
+
+ Implementation Notes
+
+ A photo album system was built for the IluvCamp Client site.
+ Much of the work on the ACS 4.0 Photo Album Package will be based
+ on the lessons learned building and maintaining this system. Some
+ of these lessons include:
+
+
+ The ability (and necessity on high volume sites) to support
+ dedicated image processing servers. As outlined in two of the
+ requirements above, numerous simultaneous image manipulations can
+ tie up resources on the main server. Low volume sites may be able
+ to handle image manipulation on the main server, but high volume
+ sites will need the ability to pass these operations off to
+ dedicated servers.
+
+ The ability to support a pool of multiple servers. The Iluvcamp
+ site used a pool of multiple servers on several machines to support
+ the high volumes of traffic. Additionally, many attributes of the
+ album structure and hierarchy were cached to improve performance.
+ When we made changes to these attributes that required cache
+ flushes, we needed to make sure the caches were flushed on all the
+ servers.
+
+ The Iluvcamp data structure mapped a specific number of images
+ to a page and then mapped the pages to albums. All of this mapping
+ and ordering information was stored in the database. This
+ essentially hard-coded the image on page ordering and the number of
+ images per page. Unfortunately this made changing the display of
+ albums from 9 images per page to 4 images per page (a mid-season
+ client request) time consuming and difficult. Given that the
+ requirements allow for easy changes to the number of thumbnails
+ displayed per page, such hard-coding should be avoided at all cost
+ in the photo album package. Photos should be mapped directly to
+ albums and pages within the album should be rendered
+ dynamically.
+
+ The amount of time it takes to retroactively change thumbnail
+ and view-size images. A client requested change of the thumbnail
+ and viewer size images on IluvCamp took several weeks of processor
+ time to modify ~ 240,000 previously uploaded images. Scheduling and
+ monitoring the conversion process was a headache. We hope to figure
+ out a easier way to make such a change.
+
+
+
+
+
+
+ Revision History
+
+
+
+
+
+ Document Revision #
+
+ Action Taken, Notes
+ When?
+ By Whom?
+
+
+
+
+
+ 0.1
+ Creation, initial draft
+ 11/15/2000
+ Tom Baginski
+
+
+
+ 0.2
+ Revisions in response to initial comments
+ 12/05/2000
+ Tom Baginski
+
+
+
+ 0.3
+ Revisions in response to more comments
+ 12/11/2000
+ Tom Baginski
+
+
+
+ 0.4
+ Minor revisions base on design experience
+ 2/2/2000
+ Tom Baginski
+
+
+
+
+
+
+
+ bags@arsdigita.com
+
+
+ Last Modified: $Date: 2003/06/10 10:08:03 $
+
+
+
+
+
Index: openacs-4/packages/photo-album/www/graphics/album.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/graphics/album.gif,v
diff -u
Binary files differ
Index: openacs-4/packages/photo-album/www/graphics/folder.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/graphics/folder.gif,v
diff -u
Binary files differ
Index: openacs-4/packages/photo-album/www/images/1x1.jpg
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/images/1x1.jpg,v
diff -u
Binary files differ
Index: openacs-4/packages/photo-album/www/images/index.vuh
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/images/index.vuh,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/photo-album/www/images/index.vuh 10 Jun 2003 10:08:34 -0000 1.1
@@ -0,0 +1,18 @@
+# /packages/photo-album/www/images/index.vuh
+# @author Tom Baginski, bags@arsdigita.com
+# #cvs-id $Id: index.vuh,v 1.1 2003/06/10 10:08:34 jeffd Exp $
+#
+# serves images
+#
+# expecting a image_id as path_info
+
+# wtem@olywa.net, 2001-09-24
+# fully reworked
+
+regexp {^([0-9]+)} [ad_conn path_info] match image_id
+
+if {[string equal [ad_parameter CheckPermissionOnImageServeP] "t"]} {
+ ad_require_permission $image_id "read"
+}
+
+cr_write_content -revision_id $image_id