Index: openacs-4/packages/photo-album/photo-album.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/photo-album.info,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/photo-album.info 10 Jun 2003 10:04:23 -0000 1.1 @@ -0,0 +1,177 @@ + + + + + Photo Album + Photo Albums + f + f + + + + oracle + postgresql + + Jeff Davis + Walter McGinnis + Tom Baginski + A photo album application that provides photo display +and grouping functionality using the ACS Content Repository. + 2002-10-29 + OpenACS + +A photo album application that provides photo display and grouping +functionality using the ACS Content Repository. + +Allows users to upload photos, store and edit attributes, and group +photos into albums and folders. Allows site administrators to set +permissions that control who can do and see what within a photo album +application. Includes sub-site support. + +Requires installation of ImageMagick on host machine. See design doc +for details. + +Heavily modified from the original Ars Digita version by +davis@xarg.net. In progres. Please do not fork it up and feed fixes +back to me. thanks. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: openacs-4/packages/photo-album/sql/test.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/Attic/test.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/test.sql 10 Jun 2003 10:04:57 -0000 1.1 @@ -0,0 +1,14 @@ +select * from acs_objects where object_id > 18553; + +select * from cr_items where item_id > 18553; + +select * from cr_revisions where revision_id > 18553; + +select * from images where image_id > 18553; + +select * from pa_photos where pa_photo_id > 18553; + +select * from cr_child_rels where rel_id > 18553; + +select object_id, acs_object__name(object_id) from acs_objects where object_id > 18553; + Index: openacs-4/packages/photo-album/sql/oracle/permissions.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/oracle/permissions.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/oracle/permissions.sql 10 Jun 2003 10:05:46 -0000 1.1 @@ -0,0 +1,27 @@ +-- PL/SQL to set up permissions/privileges for photo-album +-- +-- author: Tom Baginski, bags@arsdigita.com +-- creation date: 12/12/2000 +-- +-- $Id: permissions.sql,v 1.1 2003/06/10 10:05:46 jeffd Exp $ + +-- uses standard read, write, delete, and admin +-- for most permission checks. +-- +-- Added custom create privileges so that creation +-- of folders, albums, and photos can be controlled +-- independantly. Allows one user to control folder +-- structure while other users add albums and photos + +begin + acs_privilege.create_privilege('pa_create_album'); + acs_privilege.create_privilege('pa_create_folder'); + acs_privilege.create_privilege('pa_create_photo'); + + acs_privilege.add_child('create', 'pa_create_photo'); + acs_privilege.add_child('create', 'pa_create_album'); + acs_privilege.add_child('create', 'pa_create_folder'); +end; +/ +show errors; + Index: openacs-4/packages/photo-album/sql/oracle/photo-album-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/oracle/photo-album-create.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/oracle/photo-album-create.sql 10 Jun 2003 10:05:46 -0000 1.1 @@ -0,0 +1,214 @@ +-- /packages/photo-album/sql/photo-album-create.sql +-- +-- data model to support ACS photo ablum application +-- +-- Copyright (C) 2000-2001 ArsDigita Corporation +-- @author Tom Baginski (bags@arsdigita.com) +-- @creation-date 12/11/2000 +-- +-- @cvs-id $Id: photo-album-create.sql,v 1.1 2003/06/10 10:05:46 jeffd Exp $ +-- +-- This is free software distributed under the terms of the GNU Public +-- License. Full text of the license is available from the GNU Project: +-- http://www.fsf.org/copyleft/gpl.html + +-- ported by Walter McGinnis (wtem@olywa.net), 2001-06-10 +-- the content repository has been changed to be similar +-- to the original photo-album's storage scheme +-- (i.e. not using blobs in the database) +-- replaced photo-album's non-standard storage with +-- content-repository's standard one +-- one the key's to it is the adjustment to the content_item__new constructor + +create table pa_albums ( + pa_album_id integer + constraint pa_albums_id_fk + references cr_revisions on delete cascade + constraint pa_alubms_id_pk + primary key, + story varchar2(4000) +); + +comment on table pa_albums is ' + Table for storing custom fields of albums within content repository. + A pa_album is used to group zero or more pa_photos. +'; + +comment on column pa_albums.story is ' + Story behind the album. + This may be changed to a clob in the future if many people want to upload + stories longer than 4000 characters. + varchar2(4000) used for ease of development. +'; + + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + -- create the content type + content_type.create_type ( + content_type => 'pa_album', + pretty_name => 'Photo album', + pretty_plural => 'Photo albums', + table_name => 'pa_albums', + id_column => 'pa_album_id' + ); + + -- create content type attributes + attr_id := content_type.create_attribute ( + content_type => 'pa_album', + attribute_name => 'story', + datatype => 'text', + pretty_name => 'Story', + pretty_plural => 'Stories', + column_spec => 'varchar2(4000)' + ); +end; +/ +show errors; + + +create table pa_photos ( + pa_photo_id integer + constraint pa_photos_id_fk + references cr_revisions on delete cascade + constraint pa_photo_pk + primary key, + caption varchar2(500), + story varchar2(4000), + user_filename varchar2(250) +); + +comment on table pa_photos is ' + Table for storing custom fields of photos within content repository. + A pa_photo stores descriptive attribute information about a user + uploaded photo. The actually binary image files are stored using + associated images. +'; + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + + -- create the content type + content_type.create_type ( + content_type => 'pa_photo', + pretty_name => 'Album photo', + pretty_plural => 'Album photos', + table_name => 'pa_photos', + id_column => 'pa_photo_id' + ); + + -- create content type attributes + attr_id := content_type.create_attribute ( + content_type => 'pa_photo', + attribute_name => 'caption', + datatype => 'text', + pretty_name => 'Short caption for display under photo', + pretty_plural => 'Short captions for display under photos', + column_spec => 'varchar2(500)' + ); + + attr_id := content_type.create_attribute ( + content_type => 'pa_photo', + attribute_name => 'story', + datatype => 'text', + pretty_name => 'Story', + pretty_plural => 'Stories', + column_spec => 'varchar2(4000)' + ); + + attr_id := content_type.create_attribute ( + content_type => 'pa_photo', + attribute_name => 'user_filename', + datatype => 'text', + pretty_name => 'User filename', + pretty_plural => 'User filenames', + column_spec => 'varchar2(250)' + ); +end; +/ +show errors; + +-- wtem@olywa.net, 2001-08-3 + -- now that we are going with the new content-repository + -- storage of binaries + -- we no longer need a specialized pa_image content_type + -- it is now replaced by cr_revisions.content (which holds file name) + -- file_size is now under cr_revisions.content_size + -- we use the standar image content_type instead + +begin + content_type.register_child_type ( + parent_type => 'pa_album', + child_type => 'pa_photo' + ); + + content_type.register_child_type ( + parent_type => 'pa_photo', + child_type => 'image' + ); +end; +/ + +create table pa_package_root_folder_map ( + package_id constraint pa_pack_fldr_map_pk + primary key + constraint pa_pack_fldr_map_pack_id_fk + references apm_packages, + folder_id constraint pa_pack_fldr_map_fldr_id_fk + references cr_folders + constraint pa_pack_fldr_map_fldr_id_unq + unique +); + +create index pa_package_folder_map_by_pack on pa_package_root_folder_map (package_id, folder_id); + +comment on table pa_package_root_folder_map is ' + Table to keep track of root folder for each instance of the photo-album + Used for sub-site support. Each instance of the photo album has a unique + root folder. All folders, pa_albums, pa_photos, and images within the + package instance are descendants of the root folder. + The one-to-one mapping is done using this table to avoid adding a column to the apm_packages + that pertains only to the photo-album. +'; + +-- wtem@olywa.net, 2001-09-27 +-- replaced non-standard pa_files_to_delete with new cr_files_to_delete calls + +-- check for the two default acceptable mime_types in cr_mime_types +-- add them if necessary + +declare + v_count int; +begin + select count(*) into v_count from cr_mime_types where mime_type = 'image/jpeg'; + + if v_count = 0 then + insert into cr_mime_types values ('JPEG image', 'image/jpeg', 'jpeg'); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = 'image/gif'; + + if v_count = 0 then + insert into cr_mime_types values ('GIF image', 'image/gif', 'gif'); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = 'image/png'; + + if v_count = 0 then + insert into cr_mime_types values ('PNG image', 'image/png', 'png'); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = 'image/tiff'; + + if v_count = 0 then + insert into cr_mime_types values ('TIFF image', 'image/tiff', 'tiff'); + end if; +end; +/ +show errors; + +@@ plsql-packages.sql + +@@ permissions.sql Index: openacs-4/packages/photo-album/sql/oracle/photo-album-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/oracle/photo-album-drop.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/oracle/photo-album-drop.sql 10 Jun 2003 10:05:46 -0000 1.1 @@ -0,0 +1,212 @@ + +declare + cursor priv_cursor is + select object_id, grantee_id, privilege + from acs_permissions + where privilege = 'pa_create_photo'; + priv_val priv_cursor%ROWTYPE; +begin + for priv_val in priv_cursor + loop + acs_permission.revoke_permission ( + object_id => priv_val.object_id, + grantee_id => priv_val.grantee_id, + privilege => priv_val.privilege + ); + end loop; +end; +/ + +declare + cursor priv_cursor is + select object_id, grantee_id, privilege + from acs_permissions + where privilege = 'pa_create_album'; + priv_val priv_cursor%ROWTYPE; +begin + for priv_val in priv_cursor + loop + acs_permission.revoke_permission ( + object_id => priv_val.object_id, + grantee_id => priv_val.grantee_id, + privilege => priv_val.privilege + ); + end loop; +end; +/ + +declare + cursor priv_cursor is + select object_id, grantee_id, privilege + from acs_permissions + where privilege = 'pa_create_folder'; + priv_val priv_cursor%ROWTYPE; +begin + for priv_val in priv_cursor + loop + acs_permission.revoke_permission ( + object_id => priv_val.object_id, + grantee_id => priv_val.grantee_id, + privilege => priv_val.privilege + ); + end loop; +end; +/ + +begin + -- kill stuff in permissions.sql + + acs_privilege.remove_child('create', 'pa_create_photo'); + acs_privilege.remove_child('create', 'pa_create_album'); + acs_privilege.remove_child('create', 'pa_create_folder'); + + acs_privilege.drop_privilege('pa_create_album'); + acs_privilege.drop_privilege('pa_create_folder'); + acs_privilege.drop_privilege('pa_create_photo'); + +end; +/ + +begin + content_type.unregister_child_type ( + parent_type => 'pa_album', + child_type => 'pa_photo', + relation_tag => 'generic' + ); + + content_type.unregister_child_type ( + parent_type => 'pa_photo', + child_type => 'pa_image', + relation_tag => 'generic' + ); +end; +/ + +-- clear out all the reference that cause key violations when droping type + +-- delete images +declare + cursor image_cursor is + select item_id + from cr_items + where content_type = 'pa_image'; + image_val image_cursor%ROWTYPE; +begin + for image_val in image_cursor + loop + pa_image.delete ( + item_id => image_val.item_id + ); + end loop; +end; +/ + +-- delete photos +declare + cursor photo_cursor is + select item_id + from cr_items + where content_type = 'pa_photo'; + photo_val photo_cursor%ROWTYPE; +begin + for photo_val in photo_cursor + loop + pa_photo.delete ( + item_id => photo_val.item_id + ); + end loop; +end; +/ + +-- delete albums +declare + cursor album_cursor is + select item_id + from cr_items + where content_type = 'pa_album'; + album_val album_cursor%ROWTYPE; +begin + for album_val in album_cursor + loop + pa_album.delete ( + album_id => album_val.item_id + ); + end loop; +end; +/ + +declare + cursor folder_cursor is + select folder_id, content_type + from cr_folder_type_map where content_type = 'pa_album'; + folder_val folder_cursor%ROWTYPE; +begin + for folder_val in folder_cursor + loop + content_folder.unregister_content_type ( + folder_id => folder_val.folder_id, + content_type => folder_val.content_type + ); + end loop; +end; +/ + +drop package photo_album; + +drop package pa_album; + +drop package pa_photo; + +drop package pa_image; + +begin + acs_object_type.drop_type('pa_image'); +end; +/ + +drop table pa_images; + +begin + acs_object_type.drop_type('pa_photo'); +end; +/ + +drop table pa_photos; + +begin + acs_object_type.drop_type('pa_album'); +end; +/ + +drop table pa_albums; + +-- delete all the folder under the root folders of photo album instances +declare + cursor folder_cur is + select item_id as folder_id, level + from cr_items + where content_type = 'content_folder' + connect by prior item_id = parent_id + start with item_id in (select folder_id from pa_package_root_folder_map) + order by level desc; + folder_val folder_cur%ROWTYPE; +begin + for folder_val in folder_cur + loop + if folder_val.level = 1 then + -- folder is a root folder, delete it from maping table to avoid fk constraint violation + delete from pa_package_root_folder_map where folder_id = folder_val.folder_id; + end if; + content_folder.delete (folder_id => folder_val.folder_id); + end loop; +end; +/ + +drop table pa_package_root_folder_map; + +drop table pa_files_to_delete; + + + + + Index: openacs-4/packages/photo-album/sql/oracle/plsql-packages.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/oracle/plsql-packages.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/oracle/plsql-packages.sql 10 Jun 2003 10:05:46 -0000 1.1 @@ -0,0 +1,442 @@ +-- /packages/photo-album/sql/plsql-packages.sql +-- +-- packages to support ACS photo ablum application +-- +-- Copyright (C) 2000-2001 ArsDigita Corporation +-- @author Tom Baginski (bags@arsdigita.com) +-- @creation-date 01/08/2000 +-- +-- @cvs-id $Id: plsql-packages.sql,v 1.1 2003/06/10 10:05:46 jeffd Exp $ +-- +-- This is free software distributed under the terms of the GNU Public +-- License. Full text of the license is available from the GNU Project: +-- http://www.fsf.org/copyleft/gpl.html + +-- wtem@olywa.net, 2001-09-27 +-- pa_image package now replaced with CR standard image package + +create or replace package pa_photo +as + --/** + -- creates new pa_photo + -- associated images must be created by calling script + --*/ + 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; + + --/** + -- Deletes a single revision of a pa_photo + --*/ + procedure delete_revision ( + revision_id in acs_objects.object_id%TYPE + ); + + --/** + -- Deletes a a pa_photo and all revisions, + -- Deletes associated images (which schedules binary files for deleation) + -- + -- Be careful, cannot be undone (easily) + --*/ + procedure delete ( + item_id in acs_objects.object_id%TYPE + ); + +end pa_photo; +/ +show errors; + +create or replace package body pa_photo +as + 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 'photo', + 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 + is + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + begin + + v_item_id := content_item.new ( + name => name, + item_id => item_id, + parent_id => parent_id, + relation_tag => relation_tag, + content_type => content_type, + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + locale => locale, + context_id => context_id + ); + + v_revision_id := content_revision.new ( + title => title, + description => description, + item_id => v_item_id, + revision_id => revision_id, + publish_date => publish_date, + mime_type => mime_type, + nls_language => nls_language, + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip + ); + + insert into pa_photos + (pa_photo_id, caption, story, user_filename) + values + (v_revision_id, caption, story, user_filename); + + -- is_live => 't' not used as part of content_item.new + -- because content_item.new does not let developer specify revision_id and doesn't return revision_id, + -- revision_id needed for the insert to pa_photos + + if is_live = 't' then + content_item.set_live_revision ( + revision_id => v_revision_id + ); + end if; + + return v_item_id; + end new; + + procedure delete_revision ( + revision_id in acs_objects.object_id%TYPE + ) + is + + -- do not need to delete from the pa_photos + -- the on delete cascade will take care of this + -- during the content_revision.delete + begin + content_revision.delete ( + revision_id => revision_id + ); + + end delete_revision; + + procedure delete ( + item_id in acs_objects.object_id%TYPE + ) + is + cursor pa_image_cur is + select + child_id + from + cr_child_rels + where + parent_id = pa_photo.delete.item_id; + + begin + + -- delete all the images associated with the photo + for v_pa_image_val in pa_image_cur loop + image.delete ( + item_id => v_pa_image_val.child_id + ); + end loop; + + -- content_item.delete takes care of all revision + -- on delete cascades take care of rest + + content_item.delete ( + item_id => item_id + ); + + end delete; + +end pa_photo; +/ +show errors; + + +create or replace package pa_album +as + --/** + -- Creates a new pa_album + --*/ + 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; + + --/** + -- Deletes a single revision of a pa_album + --*/ + procedure delete_revision ( + revision_id in cr_revisions.revision_id%TYPE + ); + + --/** + -- Deletes a pa_album and all revisions + -- Album must be empty to be deleted, + -- otherwise delete throws error + --*/ + procedure delete ( + album_id in cr_items.item_id%TYPE + ); + +end pa_album; +/ +show errors; + +create or replace package body pa_album +as + 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 + is + v_item_id integer; + v_revision_id integer; + begin + v_item_id := content_item.new ( + name => name, + item_id => album_id, + parent_id => parent_id, + relation_tag => relation_tag, + content_type => content_type, + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + locale => locale, + context_id => context_id + ); + + v_revision_id := content_revision.new ( + title => title, + description => description, + item_id => v_item_id, + revision_id => revision_id, + publish_date => publish_date, + mime_type => mime_type, + nls_language => nls_language, + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip + ); + + insert into pa_albums (pa_album_id, story) + values + (v_revision_id, story); + + -- is_live => 't' not used as part of content_item.new + -- because content_item.new does not let developer specify revision_id and doesn't return revision_id, + -- revision_id needed for the insert to pa_albums + + if is_live = 't' then + content_item.set_live_revision ( + revision_id => v_revision_id + ); + end if; + + return v_item_id; + + end new; + + procedure delete_revision ( + revision_id in cr_revisions.revision_id%TYPE + ) + is + -- do not need to delete from the pa_albums + -- the on delete cascade will take care of this + -- during the content_revision.delete + begin + content_revision.delete ( + revision_id => revision_id + ); + + end delete_revision; + + procedure delete ( + album_id in cr_items.item_id%TYPE + ) + is + v_num_children integer; + begin + -- check if album is empty (no rm -r *) + select count(*) into v_num_children + from cr_items + where parent_id = pa_album.delete.album_id; + + if v_num_children > 0 then + raise_application_error(-20000, + 'The specified album ' || album_id || ' still contains photos. + An album must be empty before it can be deleted.'); + end if; + + -- content_item.delete takes care of all revision + -- on delete cascades take care of rest + + content_item.delete ( + item_id => album_id + ); + + end delete; + +end pa_album; +/ +show errors; + +--/** +-- Package does not contain new or delete procedure because +-- it contains general funcition for the photo album application +-- and is not tied to a specific object. +--*/ +create or replace package photo_album +as + + --/** + -- Returns the root folder corresponding to a package instance. + -- If root folder does not already exist, function returns null + -- + -- tcl proc that calls this function from the index page + -- takes care of the case that there is no root folder (new package instance) + -- and creates one with appropriate permissions + --*/ + + function get_root_folder ( + package_id in apm_packages.package_id%TYPE + ) return pa_package_root_folder_map.folder_id%TYPE; + + -- wtem@olywa.net, 2001-09-22 + -- wrapped up some pl-sql from tcl/photo-album-procs.tcl.pa_new_root_folder + function new_root_folder ( + package_id in apm_packages.package_id%TYPE + ) return pa_package_root_folder_map.folder_id%TYPE; + +end photo_album; +/ +show errors + +create or replace package body photo_album +as + + function get_root_folder ( + package_id in apm_packages.package_id%TYPE + ) return pa_package_root_folder_map.folder_id%TYPE + is + v_folder_id pa_package_root_folder_map.folder_id%TYPE; + begin + + -- this uses 0 as a magic number for + -- no root folder + -- in acs there will never be a folder with id 0 + + select nvl(folder_id,0) into v_folder_id + from pa_package_root_folder_map + where package_id = get_root_folder.package_id; + + if v_folder_id > 0 then + return v_folder_id; + else + return null; + end if; + + end get_root_folder; + + function new_root_folder ( + package_id in apm_packages.package_id%TYPE + ) return pa_package_root_folder_map.folder_id%TYPE + is + v_folder_id pa_package_root_folder_map.folder_id%TYPE; + v_package_name apm_packages.instance_name%TYPE; + v_package_key apm_packages.package_key%TYPE; + begin + + select instance_name, package_key + into v_package_name, v_package_key + from apm_packages + where package_id = new_root_folder.package_id; + + v_folder_id := content_folder.new ( + name => v_package_key || '_' || new_root_folder.package_id, + label => v_package_name || ' Home', + description => 'Home for ' || v_package_name + ); + + insert into pa_package_root_folder_map + (package_id, folder_id) + values + (new_root_folder.package_id, v_folder_id); + + -- allow child items to be added + content_folder.register_content_type(v_folder_id,'pa_album'); + content_folder.register_content_type(v_folder_id,'content_folder'); + + return v_folder_id; + end new_root_folder; + +end photo_album; +/ +show errors Index: openacs-4/packages/photo-album/sql/postgresql/permissions.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/permissions.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/permissions.sql 10 Jun 2003 10:06:18 -0000 1.1 @@ -0,0 +1,26 @@ +-- PL/SQL to set up permissions/privileges for photo-album +-- +-- author: Tom Baginski, bags@arsdigita.com +-- creation date: 12/12/2000 +-- +-- $Id: permissions.sql,v 1.1 2003/06/10 10:06:18 jeffd Exp $ + +-- uses standard read, write, delete, and admin +-- for most permission checks. +-- +-- Added custom create privileges so that creation +-- of folders, albums, and photos can be controlled +-- independantly. Allows one user to control folder +-- structure while other users add albums and photos + +select acs_privilege__create_privilege('pa_create_album', null, null); +select acs_privilege__create_privilege('pa_create_folder', null, null); +select acs_privilege__create_privilege('pa_create_photo', null, null); + +select acs_privilege__add_child('create', 'pa_create_photo'); +select acs_privilege__add_child('create', 'pa_create_album'); +select acs_privilege__add_child('create', 'pa_create_folder'); + + + + Index: openacs-4/packages/photo-album/sql/postgresql/photo-album-clip.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/photo-album-clip.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/photo-album-clip.sql 10 Jun 2003 10:06:19 -0000 1.1 @@ -0,0 +1,134 @@ +-- /packages/photo-album/sql/postgresql/photo-album-clip.sql +-- +-- +-- Extremely simple image clipboard to support photo +-- ordering and presentation generation +-- +-- Copyright (C) 2002 Jeff Davis +-- @author Jeff Davis davis@xarg.net +-- @creation-date 10/30/2002 +-- +-- @cvs-id $Id: photo-album-clip.sql,v 1.1 2003/06/10 10:06:19 jeffd Exp $ +-- +-- This is free software distributed under the terms of the GNU Public +-- License. Full text of the license is available from the GNU Project: +-- http://www.fsf.org/copyleft/gpl.html + +create table pa_collections ( + collection_id integer + constraint pa_collection_id_fk + references acs_objects(object_id) + constraint pa_collections_pk + primary key, + owner_id integer + constraint pa_collections_owner_id_fk + references users(user_id) on delete cascade + constraint pa_collections_owner_id_nn + not null, + title varchar(255) + constraint pa_collections_title_nn + not null +); + +comment on table pa_collections is ' + Table for saving a collection of photos +'; + +create table pa_collection_photo_map ( + collection_id integer + constraint pa_collections_fk + references pa_collections(collection_id) on delete cascade, + photo_id integer + constraint pa_photos_fk + references cr_items(item_id) on delete cascade, + constraint pa_collection_photo_map_pk + primary key (collection_id, photo_id) +); + +comment on table pa_collections is ' + Map a photo into the collection. +'; + + +select acs_object_type__create_type( + 'photo_collection', + 'Photo Collection', + 'Photo Collections', + 'acs_object', + 'pa_collections', + 'collection_id', + 'photo_album', + 'f', + 'pa_collection__name', + null + ); + + +create function pa_collection__new (integer,integer,varchar,timestamp,integer,varchar,integer) +returns integer as ' +declare + p_collection_id alias for $1; -- default null + p_owner_id alias for $2; -- default null + p_title alias for $3; + p_creation_date alias for $4; -- default now() + p_creation_user alias for $5; -- default null + p_creation_ip alias for $6; -- default null + p_context_id alias for $7; -- default null + v_collection_id pa_collections.collection_id%TYPE; +begin + v_collection_id := acs_object__new ( + p_collection_id, + ''photo_collection'', + p_creation_date, + p_creation_user, + p_creation_ip, + p_context_id + ); + + insert into pa_collections + (collection_id, owner_id, title) + values + (v_collection_id, p_owner_id, p_title); + + PERFORM acs_permission__grant_permission( + v_collection_id, + p_owner_id, + ''admin'' + ); + + return v_collection_id; + +end;' language 'plpgsql'; + +create function pa_collection__delete (integer) +returns integer as ' +declare + p_collection_id alias for $1; +begin + delete from acs_permissions + where object_id = p_collection_id; + + delete from pa_collections + where collection_id = p_collection_id; + + raise NOTICE ''Deleting photo_collection...''; + PERFORM acs_object__delete(p_collection_id); + + return 0; + +end;' language 'plpgsql'; + + +create function pa_collection__title (integer) +returns varchar as ' +declare + p_collection_id alias for $1; + v_title varchar; +begin + select title into v_title + from pa_collections + where collection_id = p_collection_id; + return v_title; +end; +' language 'plpgsql'; + Index: openacs-4/packages/photo-album/sql/postgresql/photo-album-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/photo-album-create.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/photo-album-create.sql 10 Jun 2003 10:06:19 -0000 1.1 @@ -0,0 +1,390 @@ +-- /packages/photo-album/sql/postgresql/photo-album-create.sql +-- +-- data model to support ACS photo ablum application +-- +-- Copyright (C) 2000-2001 ArsDigita Corporation +-- @author Tom Baginski (bags@arsdigita.com) +-- @creation-date 12/11/2000 +-- +-- @cvs-id $Id: photo-album-create.sql,v 1.1 2003/06/10 10:06:19 jeffd Exp $ +-- +-- This is free software distributed under the terms of the GNU Public +-- License. Full text of the license is available from the GNU Project: +-- http://www.fsf.org/copyleft/gpl.html + +-- ported by Walter McGinnis (wtem@olywa.net), 2001-06-10 +-- the content repository has been changed to be similar +-- to the original photo-album's storage scheme +-- (i.e. not using blobs in the database) +-- replaced photo-album's non-standard storage with +-- content-repository's standard one +-- one the key's to it is the adjustment to the content_item__new constructor + +create table pa_albums ( + pa_album_id integer + constraint pa_albums_id_fk + references cr_revisions on delete cascade + constraint pa_albums_id_pk + primary key, + story text, + photographer varchar(200), + taken_start timestamp, + taken_end timestamp, + iconic integer + constraint pa_albums_iconic_fk + references cr_items on delete set null +); + +comment on table pa_albums is ' + Table for storing custom fields of albums within content repository. + A pa_album is used to group zero or more pa_photos. +'; + +comment on column pa_albums.story is ' + Story behind the album. In postgresql we use the text datatype + and there is no limit on text length. This differs from the varchar2 with + Oracle. +'; + +comment on column pa_albums.iconic is ' + The photo to use as an icon for this album. If it is null a + default icon is chosen +'; + +comment on column pa_albums.photographer is ' + The photographer who took the pictures. +'; + +comment on column pa_albums.taken_start is ' + The date the photos were taken (start of range) +'; + +comment on column pa_albums.taken_start is ' + The date the photos were taken (end of range) +'; + + + -- create the content type + select content_type__create_type ( + 'pa_album', -- content_type + 'content_revision', -- supertype + 'Photo album', -- pretty_name + 'Photo albums', -- pretty_plural + 'pa_albums', -- table_name + 'pa_album_id', -- id_column + null -- name_method + ); + + -- create content type attributes + select content_type__create_attribute ( + 'pa_album', -- content_type + 'story', -- attribute_name + 'text', -- datatype + 'Story', -- pretty_name + 'Stories', -- pretty_plural + null, -- sort_order + null, -- default_value + 'text' -- column_spec + ); + + select content_type__create_attribute ( + 'pa_album', -- content_type + 'photographer', -- attribute_name + 'text', -- datatype + 'Photographer', -- pretty_name + 'Photographers', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar(200)' -- column_spec + ); + + +create table pa_photos ( + pa_photo_id integer + constraint pa_photos_id_fk + references cr_revisions on delete cascade + constraint pa_photo_pk + primary key, + caption varchar(500), + story text, + user_filename varchar(250), + camera_model varchar(250), + date_taken timestamp, + flash boolean, + focal_length numeric, + exposure_time numeric, + aperture varchar(32), + focus_distance numeric, + metering varchar(100), + sha256 varchar(64), + photographer varchar(200) +); + +comment on table pa_photos is ' + Table for storing custom fields of photos within content repository. + A pa_photo stores descriptive attribute information about a user + uploaded photo. The actually binary image files are stored using + associated images. +'; + + +-------------------------------------------------------------------------------- + select content_type__create_type ( + 'pa_photo', -- content_type + 'content_revision', -- supertype + 'Album photo', -- pretty_name + 'Album photos', -- pretty_plural + 'pa_photos', -- table_name + 'pa_photo_id', -- id_column + null -- name_method + ); + + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'story', -- attribute_name + 'text', -- datatype + 'Story', -- pretty_name + 'Stories', -- pretty_plural + null, -- sort_order + null, -- default_value + 'text' -- column_spec + ); + + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'caption', -- attribute_name + 'text', -- datatype + 'Short photo caption', -- pretty_name + 'Short photo captions', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar(500)' -- column_spec + ); + + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'user_filename', -- attribute_name + 'text', -- datatype + 'User filename', -- pretty_name + 'User filenames', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar(250)' -- column_spec + ); + + +-- +-- JCD Added for exif data 2002-07-01 +-- + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'camera_model', -- attribute_name + 'text', -- datatype + 'Camera', -- pretty_name + 'Cameras', -- pretty_plural + null, -- sort_order + null, -- default_value + 'text' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'date_taken', -- attribute_name + 'date', -- datatype + 'Date taken', -- pretty_name + 'Dates taken', -- pretty_plural + null, -- sort_order + null, -- default_value + 'timestamp' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'flash', -- attribute_name + 'boolean', -- datatype + 'Flash used', -- pretty_name + 'Flash used', -- pretty_plural + null, -- sort_order + null, -- default_value + 'boolean' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'exposure_time', -- attribute_name + 'number', -- datatype + 'Exposure time', -- pretty_name + 'Exposure times', -- pretty_plural + null, -- sort_order + null, -- default_value + 'numeric' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'aperture', -- attribute_name + 'string', -- datatype + 'Aperture', -- pretty_name + 'Apertures', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'focus_distance', -- attribute_name + 'number', -- datatype + 'Focus distance', -- pretty_name + 'Focus distances', -- pretty_plural + null, -- sort_order + null, -- default_value + 'numeric' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'metering', -- attribute_name + 'string', -- datatype + 'Metering', -- pretty_name + 'Meterings', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'sha256', -- attribute_name + 'string', -- datatype + 'SHA256', -- pretty_name + 'SHA256', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'photographer', -- attribute_name + 'text', -- datatype + 'Photographer', -- pretty_name + 'Photographers', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar(200)' -- column_spec + ); + + + -- wtem@olywa.net, 2001-08-3 + -- now that we are going with the new content-repository + -- storage of binaries + -- we no longer need a specialized pa_image content_type + -- it is now replaced by cr_revisions.content (which holds file name) + -- file_size is now under cr_revisions.content_size + -- we use the standar image content_type instead + + select content_type__register_child_type ( + 'pa_album', -- parent_type + 'pa_photo', -- child_type + 'generic', -- relation_tag + 0, -- min_n + null -- max_n + ); + + select content_type__register_child_type ( + 'pa_photo', -- parent_type + 'image', -- child_type + 'generic', -- relation_tag + 0, -- min_n + null -- max_n + ); + + +create table pa_package_root_folder_map ( + package_id integer + constraint pa_pack_fldr_map_pk + primary key + constraint pa_pack_fldr_map_pack_id_fk + references apm_packages, + folder_id integer + constraint pa_pack_fldr_map_fldr_id_fk + references cr_folders + constraint pa_pack_fldr_map_fldr_id_unq + unique +); + +create index pa_package_folder_map_by_pack on pa_package_root_folder_map (package_id, folder_id); + +comment on table pa_package_root_folder_map is ' + Table to keep track of root folder for each instance of the photo-album + Used for sub-site support. Each instance of the photo album has a unique + root folder. All folders, pa_albums, pa_photos, and images within the + package instance are descendants of the root folder. + The one-to-one mapping is done using this table to avoid adding a column to the apm_packages + that pertains only to the photo-album. +'; + +-- wtem@olywa.net, 2001-09-27 +-- replaced non-standard pa_files_to_delete with new cr_files_to_delete calls + +-- check for the two default acceptable mime_types in cr_mime_types +-- add them if necessary +-- drop function inline_0 (); + +create function inline_0 () returns integer as ' +declare + v_count integer; +begin + select count(*) into v_count from cr_mime_types where mime_type = ''image/jpeg''; + + if v_count = 0 then + insert into cr_mime_types values (''JPEG image'', ''image/jpeg'', ''jpeg''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/gif''; + + if v_count = 0 then + insert into cr_mime_types values (''GIF image'', ''image/gif'', ''gif''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/png''; + + if v_count = 0 then + insert into cr_mime_types values (''PNG image'', ''image/png'', ''png''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/tiff''; + + if v_count = 0 then + insert into cr_mime_types values (''TIFF image'', ''image/tiff'', ''tiff''); + end if; + + return 1; +end; ' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); + + +-- +-- A view to make getting the photo info out less horrible... +-- +create view all_photo_images as select i.item_id, ccr.relation_tag, im.*, p.* + from cr_items i, + cr_items i2, + pa_photos p, + cr_child_rels ccr, + images im + where i.item_id = ccr.parent_id + and p.pa_photo_id = i.live_revision + and ccr.child_id = i2.item_id + and i2.live_revision = im.image_id; + +\i permissions.sql +\i pl-pgsql.sql +\i photo-album-clip.sql + + Index: openacs-4/packages/photo-album/sql/postgresql/photo-album-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/photo-album-drop.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/photo-album-drop.sql 10 Jun 2003 10:06:20 -0000 1.1 @@ -0,0 +1,226 @@ +-- postgresql/photo-album-drop.sql + +create function tmp_pa_revoke () +returns integer as ' +declare + priv_rec RECORD; +begin + for priv_rec in select object_id, grantee_id, privilege + from acs_permissions + where privilege = ''pa_create_photo'' + loop + PERFORM acs_permission__revoke_permission ( + priv_rec.object_id, + priv_rec.grantee_id, + priv_rec.privilege + ); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_revoke (); + +drop function tmp_pa_revoke (); + +create function tmp_pa_revoke2 () +returns integer as ' +declare + priv_rec RECORD; +begin + for priv_rec in select object_id, grantee_id, privilege + from acs_permissions + where privilege = ''pa_create_album'' + loop + PERFORM acs_permission__revoke_permission ( + priv_rec.object_id, + priv_rec.grantee_id, + priv_rec.privilege + ); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_revoke2 (); + +drop function tmp_pa_revoke2 (); + +create function tmp_pa_revoke3 () +returns integer as ' +declare + priv_rec RECORD; +begin + for priv_rec in select object_id, grantee_id, privilege + from acs_permissions + where privilege = ''pa_create_folder'' + loop + PERFORM acs_permission__revoke_permission ( + priv_rec.object_id, + priv_rec.grantee_id, + priv_rec.privilege + ); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_revoke3 (); + +drop function tmp_pa_revoke3 (); + +-- kill stuff in permissions.sql +select acs_privilege__remove_child('create', 'pa_create_photo'); +select acs_privilege__remove_child('create', 'pa_create_album'); +select acs_privilege__remove_child('create', 'pa_create_folder'); + +select acs_privilege__drop_privilege('pa_create_album'); +select acs_privilege__drop_privilege('pa_create_folder'); +select acs_privilege__drop_privilege('pa_create_photo'); + +-- pa_image changed to generic image content_type + +select content_type__unregister_child_type ( + 'pa_album', + 'pa_photo', + 'generic' +); + +select content_type__unregister_child_type ( + 'pa_photo', + 'image', + 'generic' +); + +-- clear out all the reference that cause key violations when dropping type + +-- delete images +-- now that pa_image is just image +-- the query needs to be adjusted to be specific to photo-album +-- this needs to be standardized with content-repository (clearing out files) +-- there isn't currently a image__delete function +-- so this bit won't work +create function tmp_pa_image_delete () +returns integer as ' +declare + image_rec RECORD; +begin + for image_rec in select i.item_id + from cr_items i, cr_child_rels rels, + cr_items i2 + where i.content_type = ''image'' + and i2.content_type = ''pa_photo'' + and rels.child_id = i.item_id + and rels.parent_id = i2.item_id + loop + PERFORM image__delete (image_rec.item_id); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_image_delete (); + +drop function tmp_pa_image_delete (); + +-- delete photos +create function tmp_pa_photo_delete () +returns integer as ' +declare + pa_photo_rec RECORD; +begin + for pa_photo_rec in select item_id + from cr_items + where content_type = ''pa_photo'' + loop + PERFORM pa_photo__delete (pa_photo_rec.item_id); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_photo_delete (); + +drop function tmp_pa_photo_delete (); + +-- delete albums +create function tmp_pa_album_delete () +returns integer as ' +declare + pa_album_rec RECORD; +begin + for pa_album_rec in select item_id + from cr_items + where content_type = ''pa_album'' + loop + PERFORM pa_album__delete (pa_album_rec.item_id); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_album_delete (); + +drop function tmp_pa_album_delete (); + +create function tmp_pa_folder_delete () returns integer as ' +declare + folder_rec RECORD; +begin + for folder_rec in select folder_id, content_type + from cr_folder_type_map where content_type = ''pa_album'' + loop + PERFORM content_folder__unregister_content_type ( + folder_rec.folder_id, + folder_rec.content_type, + ''t'' + ); + end loop; + return 1; +end; ' language 'plpgsql'; + +select tmp_pa_folder_delete (); + +drop function tmp_pa_folder_delete (); + +-- drop package photo_album; +drop function photo_album__new_root_folder (integer); +drop function photo_album__get_root_folder (integer); + +-- this needs to drop the pa_album__ functions +-- drop package pa_album; +drop function pa_album__delete_revision (integer); +drop function pa_album__delete (integer); +drop function pa_album__new (varchar, integer, integer, boolean, integer, varchar, varchar, varchar, text, integer, timestamp, varchar, integer, timestamp, varchar); + +-- this needs to drop the pa_photo__ functions +-- drop package pa_photo; +drop function pa_photo__delete (integer); +drop function pa_photo__delete_revision (integer); +drop function pa_photo__new (varchar,integer,integer,integer,timestamp, integer, varchar, varchar, integer, varchar, varchar, boolean, timestamp, varchar, varchar, text); + +-- these drop tables as well +select content_type__drop_type('pa_photo','f','t'); + +select content_type__drop_type('pa_album','f','t'); + +-- delete all the folders under the root folders of photo album instances +-- replacing a connect by with the tree_sort business +create function tmp_pa_folder_delete2 () returns integer as ' +declare + folder_rec RECORD; +begin + for folder_rec in select i1.item_id, tree_level(i1.tree_sortkey) - tree_level(i2.tree_sortkey) as level + from cr_items i1, cr_items i2 + where i1.tree_sortkey between i2.tree_sortkey and tree_right(i2.tree_sortkey) + and i2.item_id in (select folder_id from pa_package_root_folder_map) + order by i2.item_id, level desc + loop + if folder_rec.level = 0 then + -- folder is a root folder, delete it from maping table to avoid fk constraint violation + delete from pa_package_root_folder_map where folder_id = folder_rec.item_id; + end if; + PERFORM content_folder__delete (folder_rec.folder_id); + end loop; + return 0; +end; ' language 'plpgsql'; + +select tmp_pa_folder_delete2 (); + +drop function tmp_pa_folder_delete2 (); + +drop table pa_package_root_folder_map; Index: openacs-4/packages/photo-album/sql/postgresql/photo-album-upgrade.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/Attic/photo-album-upgrade.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/photo-album-upgrade.sql 10 Jun 2003 10:06:20 -0000 1.1 @@ -0,0 +1,137 @@ +-- Add new photo attributes... + +alter table pa_photos add camera_model varchar(250); +alter table pa_photos add date_taken timestamp; +alter table pa_photos add flash boolean; +alter table pa_photos add focal_length numeric; +alter table pa_photos add exposure_time numeric; +alter table pa_photos add focus_distance numeric; +alter table pa_photos add aperture varchar(32); +alter table pa_photos add metering varchar(100); +alter table pa_photos add sha256 varchar(64); + + select content_type__create_attribute ( + 'pa_photo', -- content_type + 'camera_model', -- attribute_name + 'text', -- datatype + 'Camera', -- pretty_name + 'Cameras', -- pretty_plural + null, -- sort_order + null, -- default_value + 'text' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'date_taken', -- attribute_name + 'date', -- datatype + 'Date taken', -- pretty_name + 'Dates taken', -- pretty_plural + null, -- sort_order + null, -- default_value + 'timestamp' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'flash', -- attribute_name + 'boolean', -- datatype + 'Flash used', -- pretty_name + 'Flash used', -- pretty_plural + null, -- sort_order + null, -- default_value + 'boolean' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'exposure_time', -- attribute_name + 'number', -- datatype + 'Exposure time', -- pretty_name + 'Exposure times', -- pretty_plural + null, -- sort_order + null, -- default_value + 'number' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'aperture', -- attribute_name + 'string', -- datatype + 'Aperture', -- pretty_name + 'Apertures', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'focus_distance', -- attribute_name + 'number', -- datatype + 'Focus distance', -- pretty_name + 'Focus distances', -- pretty_plural + null, -- sort_order + null, -- default_value + 'number' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'metering', -- attribute_name + 'string', -- datatype + 'Metering', -- pretty_name + 'Meterings', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + +select content_type__create_attribute ( + 'pa_photo', -- content_type + 'sha256', -- attribute_name + 'string', -- datatype + 'SHA256', -- pretty_name + 'SHA256', -- pretty_plural + null, -- sort_order + null, -- default_value + 'varchar' -- column_spec + ); + +-- +-- Add new mime types +-- +create function inline_0 () returns integer as ' +declare + v_count integer; +begin + select count(*) into v_count from cr_mime_types where mime_type = ''image/jpeg''; + + if v_count = 0 then + insert into cr_mime_types values (''JPEG image'', ''image/jpeg'', ''jpeg''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/gif''; + + if v_count = 0 then + insert into cr_mime_types values (''GIF image'', ''image/gif'', ''gif''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/png''; + + if v_count = 0 then + insert into cr_mime_types values (''PNG image'', ''image/png'', ''png''); + end if; + + select count(*) into v_count from cr_mime_types where mime_type = ''image/tiff''; + + if v_count = 0 then + insert into cr_mime_types values (''TIFF image'', ''image/tiff'', ''tiff''); + end if; + + return 1; +end; ' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); Index: openacs-4/packages/photo-album/sql/postgresql/pl-pgsql.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/pl-pgsql.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/pl-pgsql.sql 10 Jun 2003 10:06:20 -0000 1.1 @@ -0,0 +1,324 @@ +-- /packages/photo-album/sql/postgresql/pl-pgsql.sql +-- +-- packages to support ACS photo ablum application +-- +-- need to replace the aD info with OpenACS 4 info +-- +-- Copyright (C) 2000-2001 ArsDigita Corporation +-- @author Tom Baginski (bags@arsdigita.com) +-- @creation-date 01/08/2000 +-- +-- @cvs-id $Id: pl-pgsql.sql,v 1.1 2003/06/10 10:06:20 jeffd Exp $ +-- +-- This is free software distributed under the terms of the GNU Public +-- License. Full text of the license is available from the GNU Project: +-- http://www.fsf.org/copyleft/gpl.html +-- +-- ported from sql/oracle/plsql-packages.sql + +/* +-- creates new pa_photo +-- associated pa_images must be created by calling script +*/ +-- drop function pa_photo__new (varchar,integer,integer,integer,timestamp, integer, varchar, varchar, integer, varchar, varchar, boolean, timestamp, varchar, varchar, text); + +create or replace function pa_photo__new (varchar,integer,integer,integer,timestamp, integer, varchar, varchar, integer, varchar, varchar, boolean, timestamp, varchar, varchar, text + ) returns integer as ' + declare + new__name alias for $1; + new__parent_id alias for $2; -- default null + new__item_id alias for $3; -- default null + new__revision_id alias for $4; -- default null + new__creation_date alias for $5; -- default now() + new__creation_user alias for $6; -- default null + new__creation_ip alias for $7; -- default null + new__locale alias for $8; -- default null + new__context_id alias for $9; -- default null + new__title alias for $10; -- default null + new__description alias for $11; -- default null + new__is_live alias for $12; -- default f + new__publish_date alias for $13; -- default now() + new__nls_language alias for $14; -- default null + new__caption alias for $15; -- default null + new__story alias for $16; -- default null + -- mime_type determined by image content_type + new__mime_type varchar default null; + -- the same as title + -- user_filename in pa_photos.user_filename%TYPE default null + new__content_type varchar default ''pa_photo''; + new__relation_tag varchar default null; + + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + begin + + v_item_id := content_item__new ( + new__name, + new__parent_id, + new__item_id, + new__locale, + new__creation_date, + new__creation_user, + new__context_id, + new__creation_ip, + ''content_item'', + new__content_type, + null, + null, + null, + null, + null + ); + + -- not needed in the new call to content_item__new + -- new__relation_tag, + + v_revision_id := content_revision__new ( + new__title, + new__description, + new__publish_date, + new__mime_type, + new__nls_language, + null, + v_item_id, + new__revision_id, + new__creation_date, + new__creation_user, + new__creation_ip + + ); + + insert into pa_photos + (pa_photo_id, caption, story, user_filename) + values + (v_revision_id, new__caption, new__story, new__title); + + if new__is_live = ''t'' then + PERFORM content_item__set_live_revision (v_revision_id); + end if; + + return v_item_id; +end; ' language 'plpgsql'; + +-- procedure delete_revision +-- drop function pa_photo__delete_revision (integer); + +create or replace function pa_photo__delete_revision (integer) +returns integer as ' +declare + revision_id alias for $1; + + -- do not need to delete from the pa_photos + -- the on delete cascade will take care of this + -- during the content_revision.delete +begin + PERFORM content_revision__delete (revision_id); + return 0; +end; ' language 'plpgsql'; + +-- procedure delete +-- drop function pa_photo__delete (integer); + +create or replace function pa_photo__delete (integer) +returns integer as ' +declare + del__item_id alias for $1; + v_rec record; +begin + for v_rec in + select child_id + from cr_child_rels + where parent_id = del__item_id + LOOP + PERFORM image__delete (v_rec.child_id); + end loop; + + -- content_item__delete takes care of all revisions + -- on delete cascades take care of rest + + PERFORM content_item__delete (del__item_id); + + return 0; +end; ' language 'plpgsql'; + + +/* +-- Creates a new pa_album +*/ +-- drop function pa_album__new (varchar, integer, integer, boolean, integer, varchar, varchar, varchar, text, integer, timestamp, varchar, integer, timestamp, varchar); + +create or replace function pa_album__new (varchar, integer, integer, boolean, integer, varchar, varchar, varchar, text, varchar, integer, timestamp, varchar, integer, timestamp, varchar) +returns integer as ' + declare + new__name alias for $1; + new__album_id alias for $2; + new__parent_id alias for $3; -- default null + new__is_live alias for $4; -- default f + new__creation_user alias for $5; -- default null + new__creation_ip alias for $6; -- default null + new__title alias for $7; -- default null + new__description alias for $8; -- default null + new__story alias for $9; -- default null + new__photographer alias for $10; -- default null + new__revision_id alias for $11; -- default null + new__creation_date alias for $12; -- default now() + new__locale alias for $13; -- default null + new__context_id alias for $14; -- default null + new__publish_date alias for $15; -- default now() + new__nls_language alias for $16; -- default null + + -- if we ever need another parameter space creation_date is the best bet + -- new__creation_date timestamp default now(); + new__content_type varchar default ''pa_album''; + new_relation_tag varchar default null; + new__mime_type varchar default null; + + v_item_id integer; + v_revision_id integer; + begin + v_item_id := content_item__new ( + new__name, + new__parent_id, + new__album_id, + new__locale, + new__creation_date, + new__creation_user, + new__context_id, + new__creation_ip, + ''content_item'', + new__content_type, + null, + null, + null, + null, + null + ); + + -- not needed in the new call to content_item__new + -- new__relation_tag, + + v_revision_id := content_revision__new ( + new__title, + new__description, + new__publish_date, + new__mime_type, + new__nls_language, + null, + v_item_id, + new__revision_id, + new__creation_date, + new__creation_user, + new__creation_ip + ); + + insert into pa_albums (pa_album_id, story, photographer) + values + (v_revision_id, new__story, new__photographer); + + if new__is_live = ''t'' then + PERFORM content_item__set_live_revision (v_revision_id); + end if; + + return v_item_id; +end; ' language 'plpgsql'; + +-- procedure delete_revision +-- drop function pa_album__delete_revision (integer); + +create or replace function pa_album__delete_revision (integer) +returns integer as ' +declare + revision_id alias for $1; + -- do not need to delete from the pa_albums + -- the on delete cascade will take care of this + -- during the content_revision.delete +begin + PERFORM content_revision__delete (revision_id); + return 0; +end; ' language 'plpgsql'; + +-- procedure delete +-- drop function pa_album__delete (integer); + +create or replace function pa_album__delete (integer) +returns integer as ' +declare + v_album_id alias for $1; + v_num_children integer; +begin + -- check if album is empty (no rm -r *) + select count(*) into v_num_children + from cr_items + where parent_id = v_album_id; + + if v_num_children > 0 then + raise_application_error(-20000, + ''The specified album '' || album_id || '' still contains photos. + An album must be empty before it can be deleted.''); + end if; + + -- content_item.delete takes care of all revision + -- on delete cascades take care of rest + + PERFORM content_item__delete (v_album_id); + return 0; +end; ' language 'plpgsql'; + +/* +-- Package does not contain new or delete procedure because +-- it contains general funcition for the photo album application +-- and is not tied to a specific object. +*/ + +-- drop function photo_album__get_root_folder (integer); + +create or replace function photo_album__get_root_folder (integer) +returns integer as ' +declare + v_package_id alias for $1; + v_folder_id integer; +begin + select coalesce(folder_id,0) into v_folder_id + from pa_package_root_folder_map + where package_id = v_package_id; + + if v_folder_id > 0 then + return v_folder_id; + else + return null; + end if; +end; ' language 'plpgsql'; + +-- drop function photo_album__new_root_folder (integer); + +create or replace function photo_album__new_root_folder (integer) +returns integer as ' +declare + v_package_id alias for $1; + v_folder_id pa_package_root_folder_map.folder_id%TYPE; + v_package_name apm_packages.instance_name%TYPE; + v_package_key apm_packages.package_key%TYPE; +begin + select instance_name, package_key + into v_package_name, v_package_key + from apm_packages + where package_id = v_package_id; + + v_folder_id := content_folder__new ( + v_package_key || ''_'' || v_package_id, -- name + v_package_name || '' Home'', -- label + ''Home for '' || v_package_name, -- description + null -- parent_id + ); + + insert into pa_package_root_folder_map + (package_id, folder_id) + values + (v_package_id, v_folder_id); + + -- allow child items to be added + PERFORM content_folder__register_content_type(v_folder_id,''pa_album'', ''f''); + PERFORM content_folder__register_content_type(v_folder_id,''content_folder'', ''f''); + + return v_folder_id; +end; ' language 'plpgsql'; Index: openacs-4/packages/photo-album/sql/postgresql/upgrade.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/sql/postgresql/Attic/upgrade.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/sql/postgresql/upgrade.sql 10 Jun 2003 10:06:20 -0000 1.1 @@ -0,0 +1,13 @@ +\i photo-album-clip.sql + +create view all_photo_images as select i.item_id, ccr.relation_tag, im.*, p.* + from cr_items i, + cr_items i2, + pa_photos p, + cr_child_rels ccr, + images im + where i.item_id = ccr.parent_id + and p.pa_photo_id = i.live_revision + and ccr.child_id = i2.item_id + and i2.live_revision = im.image_id; + Index: openacs-4/packages/photo-album/tcl/photo-album-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/tcl/photo-album-procs-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/tcl/photo-album-procs-oracle.xql 10 Jun 2003 10:06:42 -0000 1.1 @@ -0,0 +1,173 @@ + + + + oracle8.1.6 + + + + select photo_album.get_root_folder(:package_id) from dual + + + + + + + begin + :1 := photo_album.new_root_folder(:package_id); + end; + + + + + + + select acs.magic_object_id('$party') from dual + + + + + + + + begin + acs_permission.grant_permission ( + object_id => :new_folder_id, + grantee_id => :grantee_id, + privilege => :privilege + ); + end; + + + + + + + + + select content_folder.get_label(:folder_id) from dual + + + + + + + select parent_id as start_id, + content_item.get_title(item_id,'t') as final + from cr_items where item_id = :item_id + + + + + + + + select decode( + content_item.get_content_type(i.item_id), + 'content_folder', + 'index?folder_id=', + 'pa_album', + 'album?album_id=', + 'photo?photo_id=' + ) || i.item_id, + content_item.get_title(i.item_id,'t') + from cr_items i + connect by prior i.parent_id = i.item_id + and i.item_id != :root_folder_id + start with item_id = :start_id + order by level desc + + + + + + + select case when (select 1 + from dual + where exists (select 1 + from cr_items + where item_id = :root_folder + connect by prior parent_id = item_id + start with item_id = :item_id) + and content_item.get_content_type(:item_id) = :content_type + ) = 1 then 't' else 'f' end + from dual + + + + + + + + begin + acs_permission.grant_permission ( + object_id => :object_id, + grantee_id => :user_id, + privilege => :privilege + ); + end; + + + + + + + + + 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 => :client_filename + ); + end; + + + + + + + + + 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; + + + + + Index: openacs-4/packages/photo-album/tcl/photo-album-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/tcl/photo-album-procs-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/tcl/photo-album-procs-postgresql.xql 10 Jun 2003 10:06:42 -0000 1.1 @@ -0,0 +1,148 @@ + + + + postgresql7.1 + + + + select photo_album__get_root_folder(:package_id) + + + + + + + select photo_album__new_root_folder(:package_id) + + + + + + + select acs__magic_object_id('$party') + + + + + + + select acs_permission__grant_permission ( + :new_folder_id, -- object_id + :grantee_id, -- grantee_id + :privilege -- privilege + ) + + + + + + + select content_folder__get_label(:folder_id) + + + + + + + select parent_id as start_id, + content_item__get_title(item_id,'t') as final + from cr_items + where item_id = :item_id + + + + + + + select case + when content_item__get_content_type(i.item_id) = 'content_folder' + then 'index?folder_id=' + when content_item__get_content_type(i.item_id) = 'pa_album' + then 'album?album_id=' + else 'photo?photo_id=' + end || i.item_id, + content_item__get_title(i.item_id,'t') + from cr_items i, + (select tree_ancestor_keys(cr_items_get_tree_sortkey(:start_id)) as tree_sortkey) parents, + (select tree_sortkey from cr_items where item_id = :root_folder_id) as root + where i.tree_sortkey = parents.tree_sortkey + and i.tree_sortkey > root.tree_sortkey + order by i.tree_sortkey asc + + + + + + + select exists (select 1 + from cr_items i, cr_items i2 + where i.item_id = :item_id + and i.tree_sortkey between i2.tree_sortkey and tree_right(i2.tree_sortkey) + and i2.item_id = :root_folder + ) + and content_item__get_content_type(:item_id) = :content_type + + + + + + + + + select acs_permission__grant_permission ( + :object_id, -- object_id + :user_id, -- grantee_id + :privilege -- privilege + ) + + + + + + + select pa_photo__new ( + :image_name, -- name + :album_id, -- parent_id + :photo_id, -- item_id + :photo_rev_id, -- revision_id + current_timestamp, -- creation_date + :user_id, -- creation_user + :peeraddr, -- creation_ip + null, -- locale + :album_id, -- context_id + :client_filename, -- title + :description, -- description + 't', -- is_live + current_timestamp, -- publish_date + null, -- nls_lang + :caption, -- caption + :story -- story + ) + + + + + + + select image__new ( + :name, -- name + :photo_id, -- parent_id + :item_id, -- item_id + :rev_id, -- revision_id + :mime_type, -- mime_type + :user_id, -- creation_user + :peeraddr, -- creation_ip + :relation, -- relation_tag + :title, -- title + :description, -- description + :is_live, -- is_live + current_timestamp, -- publish_date + :path, -- path + :size, -- file_size + :height, -- height + :width -- width + ) + + + + Index: openacs-4/packages/photo-album/tcl/photo-album-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/tcl/photo-album-procs.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/tcl/photo-album-procs.tcl 10 Jun 2003 10:06:42 -0000 1.1 @@ -0,0 +1,1110 @@ +# /packages/photo-album/tcl/photo-album-procs.tcl +ad_library { + TCL library for the photo-album system + + @author Tom Baginski (bags@arsdigita.com) + @author Jeff Davis (davis@xarg.net) + + @creation-date December 14, 2000 + @cvs-id $Id: photo-album-procs.tcl,v 1.1 2003/06/10 10:06:42 jeffd Exp $ +} + +# wtem@olywa.net, 2001-09-19 +# there are several procs that we may be able to replace +# with standard cr procs now that it handles file system storage of images +# look for ### maybe redundant, replace calls? +# in front of said procs +# places to make partial changes are marked with +### probable partial change +# in front of them +# areas that have been worked on are marked +### clean +# changes that have been deferred marked +### skipped + +ad_proc -public 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 [empty_string_p $package_id] { + set package_id [ad_conn package_id] + } + return [util_memoize "pa_get_root_folder_internal $package_id"] +} + +ad_proc -private pa_get_root_folder_internal { + {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 +} { + set folder_id [db_string pa_root_folder "select photo_album.get_root_folder(:package_id) from dual"] + + if [empty_string_p $folder_id] { + set folder_id [pa_new_root_folder $package_id] + } + return $folder_id +} + +ad_proc -private pa_new_root_folder { + {package_id ""} +} { + Creates a new root folder for a package, and returns id. + A hackish function to get around the fact that we can't run + code automatically when a new package instance is created. + +} { + if [empty_string_p $package_id] { + set package_id [ad_conn package_id] + } + + # wtem@olywa.net, 2001-09-22 + # the PhotoDir parameter goes away with new CR storage scheme + + # wtem@olywa.net, 2001-09-22 + # original pl/sql wrapped up in function to simplify code and porting + db_transaction { + # create new root folder + + set new_folder_id [db_exec_plsql make_new_root { + begin + :1 := photo_album.new_root_folder(:package_id); + end; + }] + + # grant default permissions to new root folder + + # default permissions stored in package parmeter as a list of grantee privilege pairs + # the grantee can be anything that is or returns a party_id such as an integer, a subquery, + # or a function + + set perm_lst [split [ad_parameter DefaultRootFolderPrivileges] " "] + + foreach {party privilege} $perm_lst { + # wtem@olywa.net, 2001-10-15 + # urgh, originally the parameter had the pl/sql embedded in it + set grantee_id [db_string get_grantee_id "select acs.magic_object_id('$party') from dual"] + + db_exec_plsql grant_default { + begin + acs_permission.grant_permission ( + object_id => :new_folder_id, + grantee_id => :grantee_id, + privilege => :privilege + ); + end; + } + } + } + # since this is executed the first time a package instance is accessed, + # make sure the upload dir exists + + ### probable partial change + # wtem@olywa.net, 2001-09-19 + # this initializes corresponding directory structure in the file-system + # we should be able to eliminate this now that we are using CR storage + # pa_assert_dir -check_base_path "" + ### clean + return $new_folder_id +} + +ad_proc -public pa_get_folder_name { + folder_id +} { + Returns the name of a folder. +} { + return [db_string folder_name " + select content_folder.get_label(:folder_id) from dual"] +} + +ad_proc -public pa_get_folder_description { + folder_id +} { + Returns the description of a folder. +} { + return [db_string folder_description " + select description from cr_folders where folder_id = :folder_id"] +} + + +ad_proc 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. + + modified from fs_context_bar +} { + set root_folder_id [pa_get_root_folder] + + if {$item_id == $root_folder_id} { + return + } + + if [empty_string_p $final] { + # set start_id and final with a single trip to the database + + db_1row get_start_and_final "select parent_id as start_id, + content_item.get_title(item_id,'t') as final + from cr_items where item_id = :item_id" + + #set start_id [db_string parent_id " + #select parent_id from cr_items where item_id = :item_id"] + #set final [db_string title "select content_item.get_title(:item_id,'t') from dual"] + + } else { + set start_id $item_id + } + + if {$start_id != $root_folder_id} { + set context_bar [db_list_of_lists context_bar " + select decode( + content_item.get_content_type(i.item_id), + 'content_folder', + 'index?folder_id=', + 'pa_album', + 'album?album_id=', + 'photo?photo_id=' + ) || i.item_id, + content_item.get_title(i.item_id,'t') + from cr_items i + connect by prior i.parent_id = i.item_id + and i.item_id != :root_folder_id + start with item_id = :start_id + order by level desc"] + } + lappend context_bar $final + + return $context_bar +} + +# wtem@olywa.net, 2001-09-24 +### clean +ad_proc -public pa_make_file_name { + {-ext ""} + id +} { + constructs a filename for an image based on id and extention. +} { + if {![empty_string_p $ext] && ![regexp {^\.} $ext foo]} { + #add back the dot + set ext ".${ext}" + } + set total_file_name "${id}${ext}" + + return $total_file_name +} + +### maybe redundant, replace calls? +# wtem@olywa.net, 2001-09-22 +### skipped +# will handle when we get to the places where this is called +ad_proc -private pa_assert_dir { + {-check_base_path:boolean} + {dir_path} +} { + Ensures that dirname exists under the PhotoDir Directory + If -check_base_path flag specified, proc also checks if base path exists and adds it if necessary + + Won't cause an error if the directory is already there. Better than the stardard + mkdir because it will make all the directories leading up to dirname + borrowed from 3.4 download code +} { + ns_log Debug "Checking dir, pa_assert_dir" + if { $check_base_path_p } { + set dir_path "[acs_root_dir]/[ad_parameter PhotoDir]/$dir_path" + set needed_dir "" + } else { + set needed_dir "[acs_root_dir]/[ad_parameter PhotoDir]" + } + ns_log Debug "dir_path: $dir_path \n needed_dir: $needed_dir" + + set dir_list [split $dir_path /] + + foreach dir $dir_list { + ns_log Debug "Checking: $dir" + if [empty_string_p $dir] { + continue + } + append needed_dir "/$dir" + if ![file exists $needed_dir] { + ns_log Debug "Making: $dir" + ns_mkdir $needed_dir + } + } +} + +ad_proc -public 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" +} { + return [pa_is_type_in_package $folder_id "content_folder" $package_id] +} + +ad_proc -public pa_is_album_p { + album_id + {package_id ""} +} { + returns "t" if album_id is a pa_album that is a child of the root folder for the package, + else "f" +} { + return [pa_is_type_in_package $album_id "pa_album" $package_id] +} + +ad_proc -public pa_is_photo_p { + photo_id + {package_id ""} +} { + returns "t" if photo_id is a pa_photo that is a child of the root folder for the package, + else "f" +} { + return [pa_is_type_in_package $photo_id "pa_photo" $package_id] +} + +ad_proc -private pa_is_type_in_package { + item_id + content_type + {package_id ""} +} { + returns "t" if item_id is of the specified content_type and is a child of the root folder of the package, + else returns "f" +} { + set root_folder [pa_get_root_folder $package_id] + + # I check for the case that item is the root_folder first because this happens on the index page. + # Since index page accessed often, and the root_folder is within the package this avoids an unecessary + # trip to the database on a commonly accessed page. + + if {[string equal $content_type "content_folder"] && [string equal $item_id $root_folder]} { + return "t" + } else { + return [db_string check_is_type_in_package "select decode((select 1 + from dual + where exists (select 1 + from cr_items + where item_id = :root_folder + connect by prior parent_id = item_id + start with item_id = :item_id) + and content_item.get_content_type(:item_id) = :content_type + ), 1, 't', 'f') + from dual" ] + } +} + +ad_proc -public 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. +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + set grant_list [split [ad_parameter PrivilegeForCreator] ","] + foreach privilege $grant_list { + db_exec_plsql grant_privilege { + begin + acs_permission.grant_permission ( + object_id => :object_id, + grantee_id => :user_id, + privilege => :privilege + ); + end; + } + } +} + +ad_proc -public 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. +} { + set identify_string [exec identify $filename] + regexp {[ ]+([0-9]+)[x]([0-9]+)[\+]*} $identify_string x width height + uplevel "set $width_var $width" + uplevel "set $height_var $height" +} + +ad_proc -public pa_make_new_image { + base_image + new_image + geometry +} { + Uses ImageMagick program to create a file named new_image from base_image that + fits within a box defined by geometry. If geometry is just a number it will + be used for both width and height. + + ImageMagick will retain the aspect ratio of the base_image when creating the new_image + + jhead -dt is called to delete any embeded thumbnail since digital camera thumbnails + can be quite large and imagemagick does not remove them when converting (so thumbnails + can end up being 8k for the thumbnail + 32k for the embeded thumbnail). + + @param base_image original image filename + @param new_image new image filename + @param geometry string as passed to convert + +} { + # If we get an old style single number + if {[regexp {^[0-9]+$} $geometry]} { + set geometry ${geometry}x${geometry} + } + ns_log debug "pa_make_new_image: Start convert, making $new_image geometry $geometry" + exec convert -geometry $geometry -interlace None -sharpen 1x2 $base_image $new_image + exec jhead -dt $new_image + ns_log debug "pa_make_new_image: Done convert for $new_image" +} + +# wtem@olywa.net, 2001-09-22 +# replaced pa_delete_scheduled_files with standard cr_delete_scheduled_files + + +ad_proc -public pa_all_photos_in_album { + album_id +} { + returns a list of all the photo_ids in an album sorted in ascending order + pull value from cache if already there, caches result and returns result if not +} { + return [util_memoize "pa_all_photos_in_album_internal $album_id"] +} + +ad_proc -private pa_all_photos_in_album_internal { + album_id +} { + queries and returns a list of all photo_ids in album_id in ascending order +} { + return [db_list get_photo_ids {}] +} + +ad_proc -public pa_count_photos_in_album { + album_id +} { + returns count of number of photos in album_id +} { + return [llength [pa_all_photos_in_album $album_id]] +} + +ad_proc -public 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 +} { + set images_per_page [ad_parameter ThumbnailsPerPage] + set start_index [expr $images_per_page * ($page-1)] + set end_index [expr $start_index + ($images_per_page - 1)] + return [lrange [pa_all_photos_in_album $album_id] $start_index $end_index] +} + +ad_proc -public pa_count_pages_in_album { + album_id +} { + returns the number of pages in album_id +} { + return [expr int(ceil([pa_count_photos_in_album $album_id] / [ad_parameter ThumbnailsPerPage].0))] +} + +ad_proc -public 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 +} { + set photo_index [lsearch [pa_all_photos_in_album $album_id] $photo_id] + + if {$photo_index == -1 } { + return -1 + } + + return [expr int(ceil(($photo_index + 1)/ [ad_parameter ThumbnailsPerPage].0))] +} + +ad_proc -public 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. +} { + util_memoize_flush "pa_all_photos_in_album_internal $album_id" +} + +# pagination procs based on cms pagintion-procs.tcl +# when these procs get rolled into acs distribution, should use them directly + +ad_proc -deprecated pa_pagination_paginate_query { + sql + page +} { + takes a query and returns a query that accounts for pagination +} { + + set rows_per_page [ad_parameter ThumbnailsPerPage] + set start_row [expr $rows_per_page*[expr $page-1]+1] + + set query " + select * + from + ( + select + x.*, rownum as row_id + from + ($sql) x + ) ordered_sql_query_with_row_id + where + row_id between $start_row and $start_row + $rows_per_page - 1" + + return $query +} + +ad_proc -deprecated pa_pagination_get_total_pages {} { + returns the total pages in a datasource defined by $sql + The sql var must be defined at the calling level. + Uplevel used so that any binde vars in query are defined +} { + uplevel { + return [db_string get_total_pages " + select + ceil(count(*) / [ad_parameter ThumbnailsPerPage]) + from + ($sql) + "] + } +} + +ad_proc -private pa_pagination_ns_set_to_url_vars { + set_id +} { + helper procedure - turns an ns_set into a list of url_vars +} { + set url_vars {} + set size [ns_set size $set_id] + for { set i 0 } { $i < $size } { incr i } { + set key [ns_set key $set_id $i] + set value [ns_set get $set_id $key] + lappend url_vars "$key=$value" + } + + return [join $url_vars "&"] +} + + +ad_proc -public pa_pagination_context_ids { + curr + ids + {context 4} +} { + set out {} + set n_ids [llength $ids] + + # if the list is short enough just return it. + if {$n_ids < 13} { + set i 1 + foreach id $ids { + lappend out $id $i + incr i + } + return $out + } + + # what is the range about which to bracket + set start [expr [lsearch -exact $ids $curr ] - $context] + + if {[expr $start + 2 * $context + 1] > $n_ids} { + set start [expr $n_ids - 2 * $context - 1] + } + if {$start < 0} { + set start 0 + } + + # tack on 1 + if {$start > 0} { + lappend out [lindex $ids 0] 1 + } + + # context + foreach id [lrange $ids $start [expr $start + 2 * $context]] { + incr start + lappend out $id $start + } + + # tack on last + if {$start < $n_ids} { + lappend out [lrange $ids end end] $n_ids + } + + return $out +} + + +ad_proc -public pa_pagination_bar { + cur_id + all_ids + link + {what {}} +} { + 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 + next/previous +} { + if { [empty_string_p $cur_id] || [llength $all_ids] < 2 } { + return "" + } + + set cur_index [lsearch -exact $all_ids $cur_id] + set prev_id [lindex $all_ids [expr $cur_index - 1]] + set next_id [lindex $all_ids [expr $cur_index + 1]] + set photo_nav_html "" + if {![empty_string_p $what]} { + set what " $what" + } + # append the 'prev' link + append photo_nav_html "
\n" + if { ![empty_string_p $prev_id] } { + append photo_nav_html "\t
\n\t\t<< Prev$what\n\t
\n" + } + # append the 'next' link + if { ![empty_string_p $next_id] } { + append photo_nav_html "\t
\n\t\tNext$what >>\n\t
\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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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@ + +
+ + + +

Are you sure you want to delete the album "@title@"? This action cannot be reversed. + +

+

+ +
+ +
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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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. + +

$errmsg
" + } + + ad_script_abort + } + + ad_returnredirect "?folder_id=$new_folder_id" + ad_script_abort +} + +ad_return_template + Index: openacs-4/packages/photo-album/www/album-move.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album-move.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/album-move.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,41 @@ + + + + + + select parent_id from cr_items where item_id = :album_id + + + + + + + + update acs_objects + set context_id = :new_folder_id + where object_id = :album_id + + + + + + + + + select name from cr_items where item_id = :album_id + + + + + + + + select count(*) + from cr_items + where name = :folder_name + and parent_id = :new_folder_id + + + + + Index: openacs-4/packages/photo-album/www/album.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/album.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/album.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,63 @@ + +@title@ +@context@ + 1 +@page_nav@ +@message@ +

@title@

+ +

@description@

+
+ +

@story@

+
+ + + + + + + + + + + + + + + + +
@child_photo.caption@
+@child_photo.caption@
+
 
+@page_nav@ +
+

This album does not contain anything.

+
+ +

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. +

+ +

View all of your clipboards.

+
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 -N --- /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 -N --- /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 -N --- /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@ +
+@title@ +

@caption@

+
+ +

@description@

+
+ +

Story: @story@

+
+@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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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
$errMsg
" + ad_script_abort + } + } +} + +ad_returnredirect "photo?photo_id=$photo_id&collection_id=$collection_id" Index: openacs-4/packages/photo-album/www/clipboard-remove.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-remove.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/clipboard-remove.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,32 @@ +# /packages/photo-album/www/clipboard-attach.tcl +ad_page_contract { + + Detach a photo from a clipboard. + + @author Jeff Davis davis@xarg.net + @creation-date 10/30/2002 + @cvs-id $Id: clipboard-remove.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 {$collection_id > 0} { + if {[catch {db_dml unmap_photo {delete from pa_collection_photo_map where collection_id = :collection_id and photo_id = :photo_id and acs_permission__permission_p(:collection_id, :user_id, 'write') = 't'}} errMsg]} { + ad_return_error "Clipboard Remove error" "Error removing photo from clipboard
$errMsg
" + ad_script_abort + } +} + +ad_returnredirect "photo?photo_id=$photo_id&collection_id=-$collection_id" Index: openacs-4/packages/photo-album/www/clipboard-view.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboard-view.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/clipboard-view.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,41 @@ + + @title@ + @context@ + + +

+

+ Clipboard: @title@ (@owner_name@) + + + + + + + + + + + + + + + + +
+ +

+ +

No photos in the clipboard.

+
+ + +
+ @images.caption@ @images.taken@ +
+
+
+ + + 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 -N --- /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 -N --- /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. + + + + + \ No newline at end of file Index: openacs-4/packages/photo-album/www/clipboards.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/clipboards.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/clipboards.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,11 @@ +set user_id [ad_conn user_id] + +db_multirow clipboards clipboards { + SELECT c.collection_id, title, + sum(case when m.photo_id is not null then 1 else 0 end) as photos + FROM pa_collections as c left outer join pa_collection_photo_map as m + on (m.collection_id = c.collection_id) + WHERE c.owner_id = :user_id + GROUP BY c.collection_id, title + ORDER BY title +} Index: openacs-4/packages/photo-album/www/folder-add-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-add-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-add-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,33 @@ + + + + oracle8.1.6 + + + + + declare + fldr_id integer; + begin + + fldr_id :=content_folder.new ( + name => :name, + label => :label, + description => :description, + parent_id => :parent_id, + folder_id => :folder_id, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :peeraddr + ); + + -- content_folder.new automatically registers + -- the content_types of the parent to the new folder + + end; + + + + + + Index: openacs-4/packages/photo-album/www/folder-add-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-add-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-add-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,23 @@ + + + + postgresql7.1 + + + + select content_folder__new ( + :name, -- name + :label, -- label + :description, -- description + :parent_id, -- parent_id + null, -- context_id + :folder_id, -- folder_id + current_timestamp, -- creation_date + :user_id, -- creation_user + :peeraddr -- creation_ip + ) + + + + + Index: openacs-4/packages/photo-album/www/folder-add.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-add.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-add.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,5 @@ + +Create a New Folder +@context_list@ + + Index: openacs-4/packages/photo-album/www/folder-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-add.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-add.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,114 @@ +# /packages/photo-album/www/folder-add.tcl + +ad_page_contract { + + Add a folder to an existing folder + + @author Tom Baginski (bags@arsdigita.com) + @creation-date 12/8/2000 + @cvs-id $Id: folder-add.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $ +} { + parent_id:integer,notnull +} -validate { + valid_parent -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 +} + +# check for permission +ad_require_permission $parent_id pa_create_folder + + +set context_list [pa_context_bar_list -final "Create New Folder" $parent_id] + +template::form create folder_add + +template::element create folder_add folder_id -label "Sub-folder ID" \ + -datatype integer -widget hidden + +template::element create folder_add parent_id -label "Parent ID" \ + -datatype integer -widget hidden + +template::element create folder_add label -html { size 30 } \ + -label "Folder Name" -datatype text + +template::element create folder_add description -html { size 50 } \ + -label "Folder Description" -optional -datatype text + +if { [template::form is_request folder_add] } { + + set folder_id [db_nextval acs_object_id_seq] + template::element set_properties folder_add folder_id -value $folder_id + template::element set_properties folder_add parent_id -value $parent_id +} + +if { [template::form is_valid folder_add] } { + + # valid new sub-folder submission so create new subfolder + + set user_id [ad_conn user_id] + set peeraddr [ad_conn peeraddr] + set folder_id [template::element::get_value folder_add folder_id] + set parent_id [template::element::get_value folder_add parent_id] + set label [template::element::get_value folder_add label] + set description [template::element::get_value folder_add description] + + #file-safe the label into name + regsub -all { +} [string tolower $label] {_} name + regsub -all {/+} $name {-} name + + db_transaction { + + # add the folder + db_exec_plsql new_folder { + declare + fldr_id integer; + begin + + fldr_id :=content_folder.new ( + name => :name, + label => :label, + description => :description, + parent_id => :parent_id, + folder_id => :folder_id, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :peeraddr + ); + + -- content_folder.new automatically registers + -- the content_types of the parent to the new folder + + end; + } + + pa_grant_privilege_to_creator $folder_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 = :folder_id or name = :name) + and parent_id = :parent_id"] { + ad_return_complaint 1 "Either there is already a folder with the name \"$name\" + or you clicked on the button more than once. You can + return to the directory listing 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 + } + + #redirect back to index page with parent_id + ad_returnredirect "?folder_id=$parent_id" + ad_script_abort +} Index: openacs-4/packages/photo-album/www/folder-add.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-add.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-add.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,15 @@ + + + + + + + select count(*) + from cr_items + where (item_id = :folder_id or name = :name) + and parent_id = :parent_id + + + + + Index: openacs-4/packages/photo-album/www/folder-delete-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-delete-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-delete-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,16 @@ + + + + oracle8.1.6 + + + + + begin + content_folder.delete(:folder_id); + end; + + + + + Index: openacs-4/packages/photo-album/www/folder-delete-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-delete-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-delete-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,13 @@ + + + + postgresql7.1 + + + + select content_folder__delete(:folder_id) + + + + + Index: openacs-4/packages/photo-album/www/folder-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-delete.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-delete.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,16 @@ + +@title@ +@context_list@ + +
    + + + +

    Are you sure you want to delete the folder "@title@"? This action cannot be reversed. + +

    +

    + +
    + +
    Index: openacs-4/packages/photo-album/www/folder-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-delete.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-delete.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,63 @@ +# /packages/photo-album/www/folder-delete.tcl +# based on file-storage folder-delete.tcl + +ad_page_contract { + page to confirm and delete folder. + Folder must be empty to delete + + @author Tom Baginski (bags@arsdigita.com) + @creation-date 1/8/2000 + @cvs-id $Id: folder-delete.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $ +} { + folder_id:integer,notnull + {confirmed_p "f"} +} -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 delete the root folder." + } + } + + no_children -requires {not_root_folder} { + if { [db_string child_count " + select count(*) from cr_items where parent_id = :folder_id"] > 0 } { + ad_complain "We're sorry, but you cannot delete folders unless they are already empty." + } + } +} -properties { + folder_id:onevalue + title:onevalue + context_bar:onevalue +} + +# to delete a folder must have delete permission on the folder +# and write on parent folder +set parent_folder_id [db_string get_parent "select parent_id from cr_items where item_id = :folder_id"] +ad_require_permission $folder_id delete +ad_require_permission $parent_folder_id write + +if { [string equal $confirmed_p "t"] } { + # they have confirmed that they want to delete the folder + + db_exec_plsql folder_delete " + begin + content_folder.delete(:folder_id); + end;" + + ad_returnredirect "?folder_id=$parent_folder_id" + ad_script_abort +} else { + # they still need to confirm + + set title [db_string folder_name " + select label from cr_folders where folder_id = :folder_id"] + + set context_list [pa_context_bar_list -final "Delete Folder" $folder_id] + +} Index: openacs-4/packages/photo-album/www/folder-delete.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-delete.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-delete.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,27 @@ + + + + + + + select count(*) from cr_items where parent_id = :folder_id + + + + + + + select parent_id from cr_items where item_id = :folder_id + + + + + + + + select label from cr_folders where folder_id = :folder_id + + + + + Index: openacs-4/packages/photo-album/www/folder-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-edit-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-edit-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,21 @@ + + + + oracle8.1.6 + + + + + begin + content_folder.rename ( + folder_id => :folder_id, + label => :label, + description => :description + ); + end; + + + + + + Index: openacs-4/packages/photo-album/www/folder-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-edit-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-edit-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,18 @@ + + + + postgresql7.1 + + + + select content_folder__rename ( + :folder_id, -- folder_id + null, -- name + :label, -- label + :description -- description + ) + + + + + Index: openacs-4/packages/photo-album/www/folder-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-edit.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-edit.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,5 @@ + +@title@ +@context_list@ +

    Edit the Folder: + Index: openacs-4/packages/photo-album/www/folder-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/folder-edit.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/folder-edit.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,79 @@ +# /packages/photo-album/www/folder-edit.tcl + +ad_page_contract { + + Edit a folder's attributes + + @author Tom Baginski (bags@arsdigita.com) + @creation-date 12/8/2000 + @cvs-id $Id: folder-edit.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." + } + } +} -properties { + context_list:onevalue +} + +# check for permission +ad_require_permission $folder_id write + +set context_list [pa_context_bar_list -final "Edit Folder Attributes" $folder_id] + +template::form create folder_edit + +template::element create folder_edit folder_id -label "Folder ID" \ + -datatype integer -widget hidden + +template::element create folder_edit label -html { size 30 } \ + -label "Folder Name" -datatype text + +template::element create folder_edit description -html { size 50 } \ + -label "Folder Description" -optional -datatype text + +set title [pa_get_folder_name $folder_id] + +if { [template::form is_request folder_edit] } { + template::element set_properties folder_edit folder_id -value $folder_id + template::element set_properties folder_edit label -value $title + template::element set_properties folder_edit description -value [pa_get_folder_description $folder_id] +} + +if { [template::form is_valid folder_edit] } { + # vaild new sub-folder submission so create new subfolder + + set folder_id [template::element::get_value folder_edit folder_id] + set label [template::element::get_value folder_edit label] + set description [template::element::get_value folder_edit description] + + # edit the folder + db_transaction { + + db_exec_plsql edit_folder { + begin + content_folder.rename ( + folder_id => :folder_id, + label => :label, + description => :description + ); + end; + } + + } 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 + } + #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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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@ + + +

    @folder_description@

    +
    + + + + + + + + + + + + + + + + + + + +
    NameDescription
    @child.name@@child.name@@child.name@ + +@child.name@
    @child.description@
    + +
    +

    There are no items in this folder.

    +
    + + +

    View all of your clipboards.

    +
    + +

    + 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 -N --- /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 -N --- /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@ + +

    @title@

    + +@context_bar@ + +
    + + Index: openacs-4/packages/photo-album/www/pa_master.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/pa_master.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/pa_master.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1 @@ +set context_bar [eval ad_context_bar $context_list] Index: openacs-4/packages/photo-album/www/photo-add-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-add-2-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-2-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,133 @@ + + + + oracle8.1.6 + + + + + 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 => :client_filename + ); + + end; + + + + + + + + + declare + dummy integer; + begin + dummy := image.new ( + name => :base_image_name, + parent_id => :photo_id, + item_id => :base_item_id, + revision_id => :base_rev_id, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :peeraddr, + context_id => :photo_id, + title => :client_filename, + description => :description, + mime_type => :base_mime_type, + relation_tag => 'base', + is_live => 't', + filename => :base_filename_with_rel_path, + height => :base_height, + width => :base_width, + file_size => :base_n_bytes + ); + + end; + + + + + + + + declare + dummy integer; + begin + + dummy := image.new ( + name => :th_image_name, + parent_id => :photo_id, + item_id => :thumb_item_id, + revision_id => :thumb_rev_id, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :peeraddr, + context_id => :photo_id, + title => :client_filename, + description => :description, + mime_type => :thumb_mime_type, + relation_tag => 'thumb', + is_live => 't', + filename => :thumb_filename_with_rel_path, + height => :thumb_height, + width => :thumb_width, + file_size => :thumb_n_bytes + ); + + + end; + + + + + + + + declare + dummy integer; + begin + + dummy := image.new ( + name => :vw_image_name, + parent_id => :photo_id, + item_id => :viewer_item_id, + revision_id => :viewer_rev_id, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :peeraddr, + context_id => :photo_id, + title => :client_filename, + description => :description, + mime_type => :viewer_mime_type, + relation_tag => 'viewer', + is_live => 't', + filename => :viewer_filename_with_rel_path, + height => :viewer_height, + width => :viewer_width, + file_size => :viewer_n_bytes + ); + + end; + + + + + + Index: openacs-4/packages/photo-album/www/photo-add-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/Attic/photo-add-2-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-2-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,100 @@ + + + + postgresql7.1 + + + + select pa_photo__new ( + :image_name, -- name + :album_id, -- parent_id + :photo_id, -- item_id + :photo_rev_id, -- revision_id + current_timestamp, -- creation_date + :user_id, -- creation_user + :peeraddr, -- creation_ip + null, -- locale + :album_id, -- context_id + :client_filename, -- title + :description, -- description + 't', -- is_live + current_timestamp, -- publish_date + null, -- nls_language + :caption, -- caption + :story -- story + ) + + + + + + select image__new ( + :base_image_name, -- name + :photo_id, -- parent_id + :base_item_id, -- item_id + :base_rev_id, -- revision_id + :base_mime_type, -- mime_type + :user_id, -- creation_user + :peeraddr, -- creation_ip + 'base', -- relation_tag + :base_image_name, -- title + 'original image', -- description + 't', -- is_live + current_timestamp, -- publish_date + :base_filename_with_rel_path, -- path + :base_n_bytes, -- file_size + :base_height, -- height + :base_width -- width + ) + + + + + + + select image__new ( + :th_image_name, -- name + :photo_id, -- parent_id + :thumb_item_id, -- item_id + :thumb_rev_id, -- revision_id + :thumb_mime_type, -- mime_type + :user_id, -- creation_user + :peeraddr, -- creation_ip + 'thumb', -- relation_tag + :th_image_name, -- title + 'thumbnail', -- description + 't', -- is_live + current_timestamp, -- publish_date + :thumb_filename_with_rel_path, -- path + :thumb_n_bytes, -- file_size + :thumb_height, -- height + :thumb_width -- width + ) + + + + + + select image__new ( + :vw_image_name, -- name + :photo_id, -- parent_id + :viewer_item_id, -- item_id + :viewer_rev_id, -- revision_id + :viewer_mime_type, -- mime_type + :user_id, -- creation_user + :peeraddr, -- creation_ip + 'viewer', -- relation_tag + :vw_image_name, -- title + 'web sized image', -- description + 't', -- is_live + current_timestamp, -- publish_date + :viewer_filename_with_rel_path, -- path + :viewer_n_bytes, -- file_size + :viewer_height, -- height + :viewer_width -- width + ) + + + + + Index: openacs-4/packages/photo-album/www/photo-add-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add-2.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-2.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,52 @@ +# /packages/photo-album/www/photo-add-2.tcl + +ad_page_contract { + adds a photo to an album + + @author davis@xarg.net + @author bags@arsdigita.com + @creation-date 12/10/2000 + @cvs-id $Id: photo-add-2.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $ +} { + upload_file:notnull,trim + upload_file.tmpfile:tmpfile + album_id:integer,notnull + photo_id:integer,notnull + {description [db_null]} + {caption [db_null]} + {story [db_null]} +} -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." + } + } + valid_photo_id -requires {photo_id:integer} { + # supplied photo_id must not already exist + if {[db_string check_photo_id "select count(*) from cr_items where item_id = :photo_id"]} { + ad_complain "The photo already exists. Check if it is already in the album." + } + } +} + +ns_log Debug "photo-add-2: Done uploading user file, $upload_file" + +set user_id [ad_conn user_id] + +#check permission +ad_require_permission $album_id "pa_create_photo" + +set new_photo_ids [pa_load_images \ + -remove 1 \ + -client_name $upload_file \ + -description $description \ + -story $story \ + -caption $caption \ + ${upload_file.tmpfile} $album_id $user_id] + +pa_flush_photo_in_album_cache $album_id + +# page used as part of redirect so user returns to the album page containing the newly uploaded photo +set page [pa_page_of_photo_in_album [lindex $new_photo_ids 0] $album_id] + +ad_returnredirect "album?album_id=$album_id&page=$page" Index: openacs-4/packages/photo-album/www/photo-add-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add-2.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-2.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,22 @@ + + + + + + select count(*) from cr_items where item_id = :photo_id + + + + + + + + select count(*) + from cr_items + where (item_id = :photo_id or name = :client_filename) + and parent_id = :album_id + + + + + Index: openacs-4/packages/photo-album/www/photo-add-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,13 @@ + + + + oracle8.1.6 + + + + select acs_object_id_seq.nextval from dual + + + + + Index: openacs-4/packages/photo-album/www/photo-add-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,13 @@ + + + + postgresql7.1 + + + + select acs_object_id_seq.nextval + + + + + Index: openacs-4/packages/photo-album/www/photo-add.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,5 @@ + +Upload a Photo +@context_list@ + + \ No newline at end of file Index: openacs-4/packages/photo-album/www/photo-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-add.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-add.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,55 @@ +# /packages/photo-album/www/photo-add.tcl + +ad_page_contract { + + Upload a photo to an existing album + + @author Tom Baginski (bags@arsdigita.com) + @creation-date 12/10/2000 + @cvs-id $Id: photo-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_list:onevalue +} + +# check for read permission on folder +ad_require_permission $album_id pa_create_photo + +set context_list [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 photo_upload -action photo-add-2 -html {enctype multipart/form-data} + +template::element create photo_upload album_id \ + -label "album_id" -datatype integer -widget hidden + +template::element create photo_upload photo_id \ + -label "photo_id" -datatype integer -widget hidden + +template::element create photo_upload upload_file \ + -label "Choose a Photo to Upload" -help_text "Use the \"Browse...\" button find a file" -datatype text -widget file + +template::element create photo_upload caption -html { size 30 } \ + -label "Caption" -optional -help_text "OPTIONAL, Displayed on the thumbnail page" -datatype text + +template::element create photo_upload description -html { size 50} \ + -label "Photo Description" -optional -help_text "OPTIONAL, Displayed when viewing the photo" -datatype text + +template::element create photo_upload story -html { cols 50 rows 4 wrap soft } \ + -label "Photo Story" -optional -help_text "OPTIONAL" -datatype text -widget textarea + +template::element set_properties photo_upload album_id -value $album_id +template::element set_properties photo_upload photo_id -value $photo_id + +ad_return_template + + Index: openacs-4/packages/photo-album/www/photo-delete-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-delete-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-delete-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,17 @@ + + + + oracle8.1.6 + + + + + begin + pa_photo.delete (:photo_id); + end; + + + + + + Index: openacs-4/packages/photo-album/www/photo-delete-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-delete-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-delete-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,13 @@ + + + + postgresql7.1 + + + + select pa_photo__delete (:photo_id) + + + + + Index: openacs-4/packages/photo-album/www/photo-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-delete.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-delete.adp 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,16 @@ + +@title@ +@context_list@ + + +
    + + + +

    Are you sure you want to delete the photo "@title@"? This action cannot be undone. +

    +

    + +
    + +
    Index: openacs-4/packages/photo-album/www/photo-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-delete.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-delete.tcl 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,75 @@ +# photo-album/www/photo-delete.tcl + +ad_page_contract { + Confirms that user wants to delete a photo and deletes photo + + The delete removes all traces of a pa_photo and its associated images + Schedules binaries to be deleted from filesystem + Cannot be undone + + @author Tom Baginski (bags@arsdigita.com) + @creation-date 12/21/2000 + @cvs-id $Id: photo-delete.tcl,v 1.1 2003/06/10 10:07:11 jeffd Exp $ +} { + photo_id:integer,notnull + {confirmed_p "f"} +} -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 { + photo_id:onevalue + title:onevalue + path:onevalue + height:onevalue + width:onevalue +} + +# to delete a photo need delete on photo and write on parent album +set album_id [db_string get_parent_album "select parent_id from cr_items where item_id = :photo_id"] +ad_require_permission $photo_id delete +ad_require_permission $album_id write + +if { [string equal $confirmed_p "t"] } { + # they have confirmed that they want to delete the photo + # delete pa_photo object which drops all associate images and schedules binaries to be deleted + + db_exec_plsql drop_image { + begin + pa_photo.delete (:photo_id); + end; + } + + pa_flush_photo_in_album_cache $album_id + + ad_returnredirect "album?album_id=$album_id" + ad_script_abort + +} else { + # they still need to confirm + + set context_list [pa_context_bar_list -final "Delete Photo" $photo_id] + db_1row get_photo_info {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 pi + 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 = 'thumb' + and ci2.live_revision = i.image_id + and ci.item_id = :photo_id + } + + set path $image_id + + ad_return_template + } Index: openacs-4/packages/photo-album/www/photo-delete.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-delete.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-delete.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,34 @@ + + + + + + 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 + + + + + + Index: openacs-4/packages/photo-album/www/photo-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit-oracle.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-edit-oracle.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,47 @@ + + + + oracle8.1.6 + + + + select acs_object_id_seq.nextval from dual + + + + + + + + declare + dummy integer; + begin + + dummy := content_revision.new ( + title => :new_title, + description => :new_desc, + item_id => :photo_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/photo-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit-postgresql.xql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-edit-postgresql.xql 10 Jun 2003 10:07:11 -0000 1.1 @@ -0,0 +1,39 @@ + + + + postgresql7.1 + + + + select acs_object_id_seq.nextval + + + + + + + select content_revision__new ( + :new_title, -- title => + :new_desc, -- description + current_timestamp, -- publish_date + null, -- mime_type + null, -- nls_language + null, -- locale + :photo_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) + + + + + Index: openacs-4/packages/photo-album/www/photo-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/photo-edit.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-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/photo-edit.tcl,v diff -u -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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@ +
    + + @title@ + + @title@ + + +

    @caption@

    +
    +
    + +

    @description@

    +
    + +

    Story: @story@

    +
    + + + + + + @photo_nav_html@ + + + + Save this photo to print or view later + + + +
    + + Image saved to clipboard. + + + + Image removed from clipboard. + + + Save this photo to print or view later. Place in folder + + + +
    +
    + + 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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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 -N --- /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@ + +

    Name: @title@ + +

    Description: @description@ + + +

    Story: @story@ + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + +
       + + + + + +
    Hide:
    Caption:
    Story:
    Taken: @child_photo.datetaken@ @child_photo.camera_model@ @child_photo.focal_length@mm @child_photo.aperture@ Flash
    +
      
    + +
    +
    +

    This album does not contain anything. + +

    +@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 -N --- /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 -N --- /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 @@ + +ACS Administration Guide

    Photo Album
    PrevNext

    Chapter 3. 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. +

    + +


    PrevHomeNext
    Release Notes for Photo Album 4.0.1 Final Release Developer's guide
    \ No newline at end of file Index: openacs-4/packages/photo-album/www/doc/ad-doc.css =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/ad-doc.css,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/doc/ad-doc.css 10 Jun 2003 10:07:46 -0000 1.1 @@ -0,0 +1,12 @@ +code {font-family:monospace} +tt {font-family:monospace} + +..shaded{background-color:#dddddd} +...topshaded{background-color:#9999ff} +...shadedquote{background-color:#ffffcc} + +..codeblock{background-color:#eeeedd;font-family:monospace} + +p.listitem { margin-top: 0; margin-bottom: 0; } +ul { margin-bottom: 0; } +dt.listitem { margin-top: 0.5em; } Index: openacs-4/packages/photo-album/www/doc/design.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/design.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/doc/design.html 10 Jun 2003 10:07:46 -0000 1.1 @@ -0,0 +1,1377 @@ + +ACS 4 Photo Album Package Design Documentation
    Photo Album
    PrevChapter 4. Developer's guide 

    4.2. ACS 4 Photo Album Package Design Documentation

    by Tom Baginski, + bags@arsdigita.com +

    4.2.1. 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)

    • ACS 4.0 Photo Album Application Requirements +

    4.2.2. 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.

    4.2.3. 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.

    4.2.4. 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.

    4.2.5. 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.

    4.2.6. API

    4.2.6.1. 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;
        +                  
      +

    4.2.6.2. 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). +

    4.2.7. 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.

    4.2.8. 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.

    4.2.9. 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

    4.2.10. 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

    4.2.11. Authors

    • System creator, System owner, and Documentation author: Tom + Baginski, bags@arsdigita.com

    4.2.12. Revision History

    Document Revision # Action Taken, NotesWhen?By Whom?
    0.1Creation12/17/2000Tom Baginski
    0.2Editing1/9/2001Tom Baginski
    0.3Editing and additions to API and Data Model sections.2/5/2001Tom Baginski

    bags@arsdigita.com +


    PrevHome 
    Developer's guideUp 
    \ No newline at end of file Index: openacs-4/packages/photo-album/www/doc/dev-guide.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/dev-guide.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/doc/dev-guide.html 10 Jun 2003 10:07:46 -0000 1.1 @@ -0,0 +1,1234 @@ + +Developer's guide
    Photo Album
    PrevNext

    Chapter 4. Developer's guide

    4.1. ACS 4.0 Photo Album Application Requirements

    by Tom Baginski, + bags@arsdigita.com +

    4.1.1. 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.

    4.1.2. 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.

    4.1.3. 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.

    4.1.4. Use-cases and User-scenarios

    4.1.4.1. 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.

    4.1.6. Requirements

    4.1.6.1. 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.

    4.1.6.2. 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

      +

    4.1.6.3. 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.

    4.1.6.4. 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

    4.1.6.5. 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.

    4.1.6.6. 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.

    4.1.6.7. 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.

    4.1.7. 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.

    4.1.8. Revision History

    Document Revision # Action Taken, NotesWhen?By Whom?
    0.1Creation, initial draft11/15/2000Tom Baginski
    0.2Revisions in response to initial comments12/05/2000Tom Baginski
    0.3Revisions in response to more comments12/11/2000Tom Baginski
    0.4Minor revisions base on design experience2/2/2000Tom Baginski

    bags@arsdigita.com +

    Last Modified: $Date: 2003/06/10 10:07:46 $


    PrevHomeNext
    ACS Administration Guide ACS 4 Photo Album Package Design Documentation
    \ No newline at end of file Index: openacs-4/packages/photo-album/www/doc/for-everyone.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/for-everyone.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/doc/for-everyone.html 10 Jun 2003 10:07:46 -0000 1.1 @@ -0,0 +1,146 @@ + +Introduction
    Photo Album
    PrevNext

    Chapter 1. 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.


    PrevHomeNext
    Photo Album Release Notes for Photo Album 4.0.1 Final Release
    \ No newline at end of file Index: openacs-4/packages/photo-album/www/doc/index.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/photo-album/www/doc/index.html,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/photo-album/www/doc/index.html 10 Jun 2003 10:07:46 -0000 1.1 @@ -0,0 +1,257 @@ + +Photo Album

      Next
      Introduction
    \ 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 -N --- /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
    Photo Album
    PrevNext

    Chapter 2. 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.


    PrevHomeNext
    Introduction ACS Administration Guide
    \ 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 -N --- /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 -N --- /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 -N --- /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 -N 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 -N 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 -N 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 -N --- /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