Index: openacs-4/packages/file-storage/sql/oracle/file-storage-package-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/sql/oracle/file-storage-package-create.sql,v diff -u -N -r1.4.2.5 -r1.4.2.6 --- openacs-4/packages/file-storage/sql/oracle/file-storage-package-create.sql 15 Nov 2003 18:17:12 -0000 1.4.2.5 +++ openacs-4/packages/file-storage/sql/oracle/file-storage-package-create.sql 15 Nov 2003 18:47:24 -0000 1.4.2.6 @@ -37,7 +37,7 @@ -- Wrapper for content_item.new -- item_id in cr_items.item_id%TYPE default null, - title in cr_items.name%TYPE, + name in cr_items.name%TYPE, folder_id in cr_items.parent_id%TYPE, creation_user in acs_objects.creation_user%TYPE, creation_ip in acs_objects.creation_ip%TYPE, @@ -58,7 +58,7 @@ -- Wrapper to content_item__rename -- file_id in cr_items.item_id%TYPE, - title in cr_items.name%TYPE + name in cr_items.name%TYPE ); function copy_file( @@ -275,7 +275,7 @@ -- Wrapper for content_item.new -- item_id in cr_items.item_id%TYPE default null, - title in cr_items.name%TYPE, + name in cr_items.name%TYPE, folder_id in cr_items.parent_id%TYPE, creation_user in acs_objects.creation_user%TYPE, creation_ip in acs_objects.creation_ip%TYPE, @@ -288,7 +288,7 @@ then v_item_id := content_item.new( item_id => new_file.item_id, - name => new_file.title, + name => new_file.name, parent_id => new_file.folder_id, creation_user => new_file.creation_user, context_id => new_file.folder_id, @@ -298,7 +298,7 @@ ); else v_item_id := content_item.new( - name => new_file.title, + name => new_file.name, parent_id => new_file.folder_id, creation_user => new_file.creation_user, context_id => new_file.folder_id, @@ -332,13 +332,13 @@ -- Wrapper to content_item__rename -- file_id in cr_items.item_id%TYPE, - title in cr_items.name%TYPE + name in cr_items.name%TYPE ) is begin content_item.rename( item_id => file_storage.rename_file.file_id, - name => file_storage.rename_file.title + name => file_storage.rename_file.name ); end rename_file; @@ -352,7 +352,7 @@ creation_ip in acs_objects.creation_ip%TYPE ) return cr_revisions.revision_id%TYPE is - v_title cr_items.name%TYPE; + v_name cr_items.name%TYPE; v_live_revision cr_items.live_revision%TYPE; v_filename cr_revisions.title%TYPE; v_description cr_revisions.description%TYPE; @@ -369,7 +369,7 @@ select i.name, i.live_revision, r.title, r.description, r.mime_type, r.content, r.filename, r.content_length, decode(i.storage_type,'lob','t','f') - into v_title, v_live_revision, v_filename, v_description, + into v_name, v_live_revision, v_filename, v_description, v_mime_type, v_lob, v_file_path, v_content_length, v_indb_p from cr_items i, cr_revisions r @@ -380,7 +380,7 @@ -- We should probably use the copy functions of CR -- when we optimize this function v_new_file_id := file_storage.new_file( - title => v_title, + name => v_name, folder_id => file_storage.copy_file.target_folder_id, creation_user => file_storage.copy_file.creation_user, creation_ip => file_storage.copy_file.creation_ip, @@ -464,6 +464,7 @@ where cr_items.item_id = file_storage.new_version.item_id; acs_object.update_last_modified(v_folder_id,new_version.creation_user,new_version.creation_ip); + acs_object.update_last_modified(new_version.item_id,new_version.creation_user,new_version.creation_ip); return v_revision_id; @@ -473,13 +474,10 @@ function get_title( -- - -- Unfortunately, title in the file-storage context refers - -- to the name attribute in cr_items, not the title attribute in - -- cr_revisions item_id in cr_items.item_id%TYPE ) return varchar is - v_title cr_items.name%TYPE; + v_title cr_revisions.title%TYPE; v_content_type cr_items.content_type%TYPE; begin select content_type @@ -499,9 +497,10 @@ from cr_symlinks where symlink_id = get_title.item_id; else - select name into v_title - from cr_items - where item_id = get_title.item_id; + select title into v_title + from cr_revisions, cr_items + where item_id = get_title.item_id + and live_revision = revision_id; end if; end if; Index: openacs-4/packages/file-storage/sql/oracle/upgrade/upgrade-4.6.2-4.6.3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/sql/oracle/upgrade/upgrade-4.6.2-4.6.3.sql,v diff -u -N --- openacs-4/packages/file-storage/sql/oracle/upgrade/upgrade-4.6.2-4.6.3.sql 23 Jun 2003 18:47:02 -0000 1.1.2.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,708 +0,0 @@ --- Need to recreate package, to add user and IP to update_last_modified --- $Id - -create or replace package file_storage -as - - function get_root_folder( - -- - -- Returns the root folder corresponding to a particular - -- package instance. - -- - package_id in apm_packages.package_id%TYPE - ) return fs_root_folders.folder_id%TYPE; - - function get_package_id( - item_id in cr_items.item_id%TYPE - ) return fs_root_folders.package_id%TYPE; - - function new_root_folder( - -- - -- Creates a new root folder - -- - package_id in apm_packages.package_id%TYPE, - folder_name in cr_folders.label%TYPE default null, - description in cr_folders.description%TYPE default null - ) return fs_root_folders.folder_id%TYPE; - - function new_file( - -- - -- Create a file in CR in preparation for actual storage - -- Wrapper for content_item.new - -- - item_id in cr_items.item_id%TYPE default null, - title in cr_items.name%TYPE, - folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE, - indb_p in char default 't' - ) return cr_items.item_id%TYPE; - - procedure delete_file( - -- - -- Delete a file and all its version - -- Wrapper to content_item.delete - -- - file_id in cr_items.item_id%TYPE - ); - - procedure rename_file( - -- - -- Rename a file and all - -- Wrapper to content_item__rename - -- - file_id in cr_items.item_id%TYPE, - title in cr_items.name%TYPE - ); - - function copy_file( - -- - -- Copy a file, but only copy the live_revision - -- - file_id in cr_items.item_id%TYPE, - target_folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_revisions.revision_id%TYPE; - - procedure move_file( - -- - -- Move a file, and all its versions, to a new folder - -- - file_id in cr_items.item_id%TYPE, - target_folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ); - - function get_title( - -- - -- Unfortunately, title in the file-storage context refers - -- to the name attribute in cr_items, not the title attribute in - -- cr_revisions - item_id in cr_items.item_id%TYPE - ) return varchar; - - function get_parent_id( - item_id in cr_items.item_id%TYPE - ) return cr_items.item_id%TYPE; - - function get_content_type( - -- - -- Wrapper for content_item. get_content_type - -- - item_id in cr_items.item_id%TYPE - ) return cr_items.content_type%TYPE; - - function get_folder_name( - -- - -- Wrapper for content_folder__get_label - -- - folder_id in cr_folders.folder_id%TYPE - ) return cr_folders.label%TYPE; - - function new_version( - -- - -- Create a new version of a file - -- Wrapper for content_revision.new - -- - filename in cr_revisions.title%TYPE, - description in cr_revisions.description%TYPE, - mime_type in cr_revisions.mime_type%TYPE, - item_id in cr_items.item_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_revisions.revision_id%TYPE; - - function delete_version( - -- - -- Delete a version of a file - -- - file_id in cr_items.item_id%TYPE, - version_id in cr_revisions.revision_id%TYPE - ) return cr_items.parent_id%TYPE; - - function new_folder( - -- - -- Create a folder - -- - name in cr_items.name%TYPE, - folder_name in cr_folders.label%TYPE, - parent_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_folders.folder_id%TYPE; - - procedure delete_folder( - -- - -- Delete a folder - -- - folder_id in cr_folders.folder_id%TYPE - ); - -end file_storage; -/ -show errors - -create or replace package body file_storage -as - - function get_root_folder( - package_id in apm_packages.package_id%TYPE - ) return fs_root_folders.folder_id%TYPE - is - v_folder_id fs_root_folders.folder_id%TYPE; - v_count integer; - begin - select count(*) - into v_count - from fs_root_folders - where package_id = get_root_folder.package_id; - - if v_count > 0 then - select folder_id - into v_folder_id - from fs_root_folders - where package_id = get_root_folder.package_id; - else - -- must be a new instance. Gotta create a new root folder - v_folder_id := new_root_folder(package_id); - end if; - - return v_folder_id; - end get_root_folder; - - function get_package_id( - item_id in cr_items.item_id%TYPE - ) return fs_root_folders.package_id%TYPE - is - v_package_id fs_root_folders.package_id%TYPE; - begin - select fs_root_folders.package_id - into v_package_id - from fs_root_folders, - (select cr_items.item_id - from cr_items - connect by prior cr_items.parent_id = cr_items.item_id - start with cr_items.item_id = get_package_id.item_id) this - where fs_root_folders.folder_id = this.item_id; - - return v_package_id; - - exception when NO_DATA_FOUND then - return null; - end get_package_id; - - function new_root_folder( - -- - -- A hackish function to get around the fact that we can't run - -- code automatically when a new package instance is created. - -- - package_id in apm_packages.package_id%TYPE, - folder_name in cr_folders.label%TYPE default null, - description in cr_folders.description%TYPE default null - ) return fs_root_folders.folder_id%TYPE - is - v_folder_id fs_root_folders.folder_id%TYPE; - v_package_name apm_packages.instance_name%TYPE; - v_package_key apm_packages.package_key%TYPE; - v_folder_name cr_folders.label%TYPE; - v_description cr_folders.description%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; - - if new_root_folder.folder_name is null - then - v_folder_name := v_package_name || ' Root Folder'; - else - v_folder_name := folder_name; - end if; - - if new_root_folder.description is null - then - v_description := 'Root folder for the file-storage system. All other folders in file storage are subfolders of this one.'; - else - v_description := description; - end if; - - v_folder_id := content_folder.new( - name => v_package_key || '_' || package_id, - label => v_folder_name, - description => v_description - ); - - insert - into fs_root_folders - (package_id, folder_id) - values - (package_id, v_folder_id); - - -- allow child items to be added - content_folder.register_content_type(v_folder_id,'content_revision','t'); - content_folder.register_content_type(v_folder_id,'content_folder','t'); - content_folder.register_content_type(v_folder_id,'content_extlink','t'); - content_folder.register_content_type(v_folder_id,'content_symlink','t'); - - -- set up default permissions - acs_permission.grant_permission( - object_id => v_folder_id, - grantee_id => acs.magic_object_id('the_public'), - privilege => 'read' - ); - - acs_permission.grant_permission( - object_id => v_folder_id, - grantee_id => acs.magic_object_id('registered_users'), - privilege => 'write' - ); - - return v_folder_id; - end new_root_folder; - - function new_file( - -- - -- Create a file in CR in preparation for actual storage - -- Wrapper for content_item.new - -- - item_id in cr_items.item_id%TYPE default null, - title in cr_items.name%TYPE, - folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE, - indb_p in char default 't' - ) return cr_items.item_id%TYPE - is - v_item_id cr_items.item_id%TYPE; - begin - if new_file.indb_p = 't' - then - v_item_id := content_item.new( - item_id => new_file.item_id, - name => new_file.title, - parent_id => new_file.folder_id, - creation_user => new_file.creation_user, - context_id => new_file.folder_id, - creation_ip => new_file.creation_ip, - content_type => 'file_storage_object', - item_subtype => 'content_item' - ); - else - v_item_id := content_item.new( - name => new_file.title, - parent_id => new_file.folder_id, - creation_user => new_file.creation_user, - context_id => new_file.folder_id, - creation_ip => new_file.creation_ip, - content_type => 'file_storage_object', - item_subtype => 'content_item', - storage_type => 'file' - ); - end if; - - acs_object.update_last_modified(file_storage.new_file.folder_id,new_file.creation_user,new_file.creation_ip); - - return v_item_id; - end new_file; - - procedure delete_file( - -- - -- Delete a file and all its version - -- Wrapper to content_item__delete - -- - file_id in cr_items.item_id%TYPE - ) - is - begin - content_item.delete(item_id => file_storage.delete_file.file_id); - end delete_file; - - procedure rename_file( - -- - -- Rename a file and all - -- Wrapper to content_item__rename - -- - file_id in cr_items.item_id%TYPE, - title in cr_items.name%TYPE - ) - is - begin - content_item.rename( - item_id => file_storage.rename_file.file_id, - name => file_storage.rename_file.title - ); - end rename_file; - - function copy_file( - -- - -- Copy a file, but only copy the live_revision - -- - file_id in cr_items.item_id%TYPE, - target_folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_revisions.revision_id%TYPE - is - v_title cr_items.name%TYPE; - v_live_revision cr_items.live_revision%TYPE; - v_filename cr_revisions.title%TYPE; - v_description cr_revisions.description%TYPE; - v_mime_type cr_revisions.mime_type%TYPE; - v_content_length cr_revisions.content_length%TYPE; - v_lob cr_revisions.content%TYPE; - v_file_path cr_revisions.filename%TYPE; - v_new_file_id cr_items.item_id%TYPE; - v_new_version_id cr_revisions.revision_id%TYPE; - v_indb_p char; - begin - -- We copy only the title from the file being copied, and attributes of the - -- live revision - select i.name, i.live_revision, r.title, r.description, - r.mime_type, r.content, r.filename, r.content_length, - decode(i.storage_type,'lob','t','f') - into v_title, v_live_revision, v_filename, v_description, - v_mime_type, v_lob, v_file_path, v_content_length, - v_indb_p - from cr_items i, cr_revisions r - where r.item_id = i.item_id - and r.revision_id = i.live_revision - and i.item_id = file_storage.copy_file.file_id; - - -- We should probably use the copy functions of CR - -- when we optimize this function - v_new_file_id := file_storage.new_file( - title => v_title, - folder_id => file_storage.copy_file.target_folder_id, - creation_user => file_storage.copy_file.creation_user, - creation_ip => file_storage.copy_file.creation_ip, - indb_p => v_indb_p - ); - - v_new_version_id := file_storage.new_version( - filename => v_filename, - description => v_description, - mime_type => v_mime_type, - item_id => v_new_file_id, - creation_user => file_storage.copy_file.creation_user, - creation_ip => file_storage.copy_file.creation_ip - ); - - -- Oracle is easier, since lobs are true lobs - -- For now, we simply copy the file name - update cr_revisions - set filename = v_file_path, - content = v_lob, - content_length = v_content_length - where revision_id = v_new_version_id; - - acs_object.update_last_modified(file_storage.copy_file.target_folder_id,file_storage.copy_file.creation_user,file_storage.copy_file.creation_ip); - - return v_new_version_id; - end copy_file; - - procedure move_file( - -- - -- Move a file, and all its versions, to a new folder - -- - file_id in cr_items.item_id%TYPE, - target_folder_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) - is - begin - content_item.move( - item_id => file_storage.move_file.file_id, - target_folder_id => file_storage.move_file.target_folder_id - ); - - acs_object.update_last_modified(file_storage.move_file.target_folder_id,file_storage.move_file.creation_user,file_storage.move_file.creation_ip); - - end; - - function new_version( - -- - -- Create a new version of a file - -- Wrapper for content_revision.new - -- - filename in cr_revisions.title%TYPE, - description in cr_revisions.description%TYPE, - mime_type in cr_revisions.mime_type%TYPE, - item_id in cr_items.item_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_revisions.revision_id%TYPE - is - v_revision_id cr_revisions.revision_id%TYPE; - v_folder_id cr_items.parent_id%TYPE; - begin - -- Create a revision - v_revision_id := content_revision.new( - title => new_version.filename, - description => new_version.description, - mime_type => new_version.mime_type, - item_id => new_version.item_id, - creation_user => new_version.creation_user, - creation_ip => new_version.creation_ip - ); - - -- Make live the newly created revision - content_item.set_live_revision(revision_id => v_revision_id); - - select cr_items.parent_id - into v_folder_id - from cr_items - where cr_items.item_id = file_storage.new_version.item_id; - - acs_object.update_last_modified(v_folder_id,new_version.creation_user,new_version.creation_ip); - - return v_revision_id; - - exception when NO_DATA_FOUND then - return v_revision_id; - end new_version; - - function get_title( - -- - -- Unfortunately, title in the file-storage context refers - -- to the name attribute in cr_items, not the title attribute in - -- cr_revisions - item_id in cr_items.item_id%TYPE - ) return varchar - is - v_title cr_items.name%TYPE; - v_content_type cr_items.content_type%TYPE; - begin - select content_type - into v_content_type - from cr_items - where item_id = get_title.item_id; - - if v_content_type = 'content_folder' - then - select label - into v_title - from cr_folders - where folder_id = get_title.item_id; - else if v_content_type = 'content_symlink' - then - select label into v_title - from cr_symlinks - where symlink_id = get_title.item_id; - else - select name into v_title - from cr_items - where item_id = get_title.item_id; - end if; - end if; - - return v_title; - end get_title; - - function get_parent_id( - item_id in cr_items.item_id%TYPE - ) return cr_items.item_id%TYPE - is - v_parent_id cr_items.item_id%TYPE; - begin - select parent_id - into v_parent_id - from cr_items - where item_id = get_parent_id.item_id; - - return v_parent_id; - end get_parent_id; - - function get_content_type( - -- - -- Wrapper for content_item. get_content_type - -- - item_id in cr_items.item_id%TYPE - ) return cr_items.content_type%TYPE - is - v_content_type cr_items.content_type%TYPE; - begin - v_content_type := content_item.get_content_type( - item_id => file_storage.get_content_type.item_id - ); - - return v_content_type; - end get_content_type; - - function get_folder_name( - -- - -- Wrapper for content_folder.get_label - -- - folder_id in cr_folders.folder_id%TYPE - ) return cr_folders.label%TYPE - is - v_folder_name cr_folders.label%TYPE; - begin - v_folder_name := content_folder.get_label( - folder_id => file_storage.get_folder_name.folder_id - ); - - return v_folder_name; - end get_folder_name; - - function delete_version( - -- - -- Delete a version of a file - -- - file_id in cr_items.item_id%TYPE, - version_id in cr_revisions.revision_id%TYPE - ) return cr_items.parent_id%TYPE - is - v_parent_id cr_items.parent_id%TYPE; - begin - if file_storage.delete_version.version_id = content_item.get_live_revision(file_storage.delete_version.file_id) - then - content_revision.delete(file_storage.delete_version.version_id); - content_item.set_live_revision( - content_item.get_latest_revision(file_storage.delete_version.file_id) - ); - else - content_revision.delete(file_storage.delete_version.version_id); - end if; - - -- If the live revision is null, we have deleted the last version above - select decode(live_revision, null, parent_id, 0) - into v_parent_id - from cr_items - where item_id = file_storage.delete_version.file_id; - - -- Unfortunately, due to PostgreSQL behavior with regards referential integrity, - -- we cannot delete the content_item entry if there are no more revisions. - return v_parent_id; - end delete_version; - - function new_folder( - -- - -- Create a folder - -- - name in cr_items.name%TYPE, - folder_name in cr_folders.label%TYPE, - parent_id in cr_items.parent_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE - ) return cr_folders.folder_id%TYPE - is - v_folder_id cr_folders.folder_id%TYPE; - begin - -- Create a new folder - v_folder_id := content_folder.new( - name => file_storage.new_folder.name, - label => file_storage.new_folder.folder_name, - parent_id => file_storage.new_folder.parent_id, - creation_user => file_storage.new_folder.creation_user, - creation_ip => file_storage.new_folder.creation_ip - ); - - -- register the standard content types - content_folder.register_content_type( - v_folder_id, -- folder_id - 'content_revision', -- content_type - 't' -- include_subtypes - ); - - content_folder.register_content_type( - v_folder_id, -- folder_id - 'content_folder', -- content_type - 't' -- include_subtypes - ); - - content_folder.register_content_type( - v_folder_id, -- folder_id - 'content_extlink', -- content_type - 't' -- include_subtypes - ); - - content_folder.register_content_type( - v_folder_id, -- folder_id - 'content_symlink', -- content_type - 't' -- include_subtypes - ); - - -- Give the creator admin privileges on the folder - acs_permission.grant_permission( - v_folder_id, -- object_id - file_storage.new_folder.creation_user, -- grantee_id - 'admin' -- privilege - ); - - return v_folder_id; - end new_folder; - - procedure delete_folder( - -- - -- Delete a folder - -- - folder_id in cr_folders.folder_id%TYPE - ) - is - begin - content_folder.delete( - folder_id => file_storage.delete_folder.folder_id - ); - end delete_folder; - -end file_storage; -/ -show errors; - --- JS: BEFORE DELETE TRIGGER to clean up CR -create or replace trigger fs_package_items_delete_trig -before delete on fs_root_folders -for each row -declare - cursor v_cursor is - select item_id,content_type - from cr_items - where item_id != :old.folder_id - connect by parent_id = prior item_id - start with item_id = :old.folder_id - order by level desc; -begin - for v_rec in v_cursor - loop - -- We delete the item. On delete cascade should take care - -- of deletion of revisions. - if v_rec.content_type = 'file_storage_object' - then - content_item.delete(v_rec.item_id); - end if; - - -- Instead of doing an if-else, we make sure we are deleting a folder. - if v_rec.content_type = 'content_folder' - then - content_folder.delete(v_rec.item_id); - end if; - - -- Instead of doing an if-else, we make sure we are deleting a folder. - if v_rec.content_type = 'content_symlink' - then - content_symlink.delete(v_rec.item_id); - end if; - - -- Instead of doing an if-else, we make sure we are deleting a folder. - if v_rec.content_type = 'content_extlink' - then - content_extlink.delete(v_rec.item_id); - end if; - - end loop; -end; -/ -show errors; - --- JS: AFTER DELETE TRIGGER to clean up last entry in CR -create or replace trigger fs_root_folder_delete_trig -after delete on fs_root_folders -for each row -begin - content_folder.delete(:old.folder_id); -end; -/ -show errors; Index: openacs-4/packages/file-storage/sql/oracle/upgrade/upgrade-4.6.3-4.8.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/sql/oracle/upgrade/Attic/upgrade-4.6.3-4.8.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/file-storage/sql/oracle/upgrade/upgrade-4.6.3-4.8.sql 15 Nov 2003 18:47:25 -0000 1.1.2.1 @@ -0,0 +1,729 @@ +-- +-- @author Dave Bauer (dave@thedesignexperience.org) +-- @creation-date 2003-11-15 +-- @cvs-id $Id: upgrade-4.6.3-4.8.sql,v 1.1.2.1 2003/11/15 18:47:25 daveb Exp $ +-- + + +create or replace package file_storage +as + + function get_root_folder( + -- + -- Returns the root folder corresponding to a particular + -- package instance. + -- + package_id in apm_packages.package_id%TYPE + ) return fs_root_folders.folder_id%TYPE; + + function get_package_id( + item_id in cr_items.item_id%TYPE + ) return fs_root_folders.package_id%TYPE; + + function new_root_folder( + -- + -- Creates a new root folder + -- + package_id in apm_packages.package_id%TYPE, + folder_name in cr_folders.label%TYPE default null, + description in cr_folders.description%TYPE default null, + name in cr_items.name%TYPE default null + ) return fs_root_folders.folder_id%TYPE; + + function new_file( + -- + -- Create a file in CR in preparation for actual storage + -- Wrapper for content_item.new + -- + item_id in cr_items.item_id%TYPE default null, + name in cr_items.name%TYPE, + folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE, + indb_p in char default 't' + ) return cr_items.item_id%TYPE; + + procedure delete_file( + -- + -- Delete a file and all its version + -- Wrapper to content_item.delete + -- + file_id in cr_items.item_id%TYPE + ); + + procedure rename_file( + -- + -- Rename a file and all + -- Wrapper to content_item__rename + -- + file_id in cr_items.item_id%TYPE, + name in cr_items.name%TYPE + ); + + function copy_file( + -- + -- Copy a file, but only copy the live_revision + -- + file_id in cr_items.item_id%TYPE, + target_folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_revisions.revision_id%TYPE; + + procedure move_file( + -- + -- Move a file, and all its versions, to a new folder + -- + file_id in cr_items.item_id%TYPE, + target_folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ); + + function get_title( + -- + -- Unfortunately, title in the file-storage context refers + -- to the name attribute in cr_items, not the title attribute in + -- cr_revisions + item_id in cr_items.item_id%TYPE + ) return varchar; + + function get_parent_id( + item_id in cr_items.item_id%TYPE + ) return cr_items.item_id%TYPE; + + function get_content_type( + -- + -- Wrapper for content_item. get_content_type + -- + item_id in cr_items.item_id%TYPE + ) return cr_items.content_type%TYPE; + + function get_folder_name( + -- + -- Wrapper for content_folder__get_label + -- + folder_id in cr_folders.folder_id%TYPE + ) return cr_folders.label%TYPE; + + function new_version( + -- + -- Create a new version of a file + -- Wrapper for content_revision.new + -- + filename in cr_revisions.title%TYPE, + description in cr_revisions.description%TYPE, + mime_type in cr_revisions.mime_type%TYPE, + item_id in cr_items.item_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_revisions.revision_id%TYPE; + + function delete_version( + -- + -- Delete a version of a file + -- + file_id in cr_items.item_id%TYPE, + version_id in cr_revisions.revision_id%TYPE + ) return cr_items.parent_id%TYPE; + + function new_folder( + -- + -- Create a folder + -- + name in cr_items.name%TYPE, + folder_name in cr_folders.label%TYPE, + parent_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_folders.folder_id%TYPE; + + procedure delete_folder( + -- + -- Delete a folder + -- + folder_id in cr_folders.folder_id%TYPE + ); + +end file_storage; +/ +show errors + +create or replace package body file_storage +as + + function get_root_folder( + package_id in apm_packages.package_id%TYPE + ) return fs_root_folders.folder_id%TYPE + is + v_folder_id fs_root_folders.folder_id%TYPE; + v_count integer; + begin + select count(*) + into v_count + from fs_root_folders + where package_id = get_root_folder.package_id; + + if v_count > 0 then + select folder_id + into v_folder_id + from fs_root_folders + where package_id = get_root_folder.package_id; + else + -- must be a new instance. Gotta create a new root folder + v_folder_id := new_root_folder(package_id); + end if; + + return v_folder_id; + end get_root_folder; + + function get_package_id( + item_id in cr_items.item_id%TYPE + ) return fs_root_folders.package_id%TYPE + is + v_package_id fs_root_folders.package_id%TYPE; + begin + select fs_root_folders.package_id + into v_package_id + from fs_root_folders, + (select cr_items.item_id + from cr_items + connect by prior cr_items.parent_id = cr_items.item_id + start with cr_items.item_id = get_package_id.item_id) this + where fs_root_folders.folder_id = this.item_id; + + return v_package_id; + + exception when NO_DATA_FOUND then + return null; + end get_package_id; + + function new_root_folder( + -- + -- A hackish function to get around the fact that we can't run + -- code automatically when a new package instance is created. + -- + package_id in apm_packages.package_id%TYPE, + folder_name in cr_folders.label%TYPE default null, + description in cr_folders.description%TYPE default null, + name in cr_items.name%TYPE default null + ) return fs_root_folders.folder_id%TYPE + is + v_folder_id fs_root_folders.folder_id%TYPE; + v_package_name apm_packages.instance_name%TYPE; + v_package_key apm_packages.package_key%TYPE; + v_folder_name cr_folders.label%TYPE; + v_description cr_folders.description%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; + + if new_root_folder.folder_name is null + then + v_folder_name := v_package_name || ' Root Folder'; + else + v_folder_name := folder_name; + end if; + + if new_root_folder.description is null + then + v_description := 'Root folder for the file-storage system. All other folders in file storage are subfolders of this one.'; + else + v_description := description; + end if; + + v_folder_id := content_folder.new( + name => nvl(new_root_folder.name,v_package_key || '_' || package_id), + label => v_folder_name, + description => v_description + ); + + insert + into fs_root_folders + (package_id, folder_id) + values + (package_id, v_folder_id); + + -- allow child items to be added + content_folder.register_content_type(v_folder_id,'content_revision','t'); + content_folder.register_content_type(v_folder_id,'content_folder','t'); + content_folder.register_content_type(v_folder_id,'content_extlink','t'); + content_folder.register_content_type(v_folder_id,'content_symlink','t'); + + -- set up default permissions + acs_permission.grant_permission( + object_id => v_folder_id, + grantee_id => acs.magic_object_id('the_public'), + privilege => 'read' + ); + + acs_permission.grant_permission( + object_id => v_folder_id, + grantee_id => acs.magic_object_id('registered_users'), + privilege => 'write' + ); + + return v_folder_id; + end new_root_folder; + + function new_file( + -- + -- Create a file in CR in preparation for actual storage + -- Wrapper for content_item.new + -- + item_id in cr_items.item_id%TYPE default null, + name in cr_items.name%TYPE, + folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE, + indb_p in char default 't' + ) return cr_items.item_id%TYPE + is + v_item_id cr_items.item_id%TYPE; + begin + if new_file.indb_p = 't' + then + v_item_id := content_item.new( + item_id => new_file.item_id, + name => new_file.name, + parent_id => new_file.folder_id, + creation_user => new_file.creation_user, + context_id => new_file.folder_id, + creation_ip => new_file.creation_ip, + content_type => 'file_storage_object', + item_subtype => 'content_item' + ); + else + v_item_id := content_item.new( + name => new_file.name, + parent_id => new_file.folder_id, + creation_user => new_file.creation_user, + context_id => new_file.folder_id, + creation_ip => new_file.creation_ip, + content_type => 'file_storage_object', + item_subtype => 'content_item', + storage_type => 'file' + ); + end if; + + acs_object.update_last_modified(file_storage.new_file.folder_id,new_file.creation_user,new_file.creation_ip); + + return v_item_id; + end new_file; + + procedure delete_file( + -- + -- Delete a file and all its version + -- Wrapper to content_item__delete + -- + file_id in cr_items.item_id%TYPE + ) + is + begin + content_item.delete(item_id => file_storage.delete_file.file_id); + end delete_file; + + procedure rename_file( + -- + -- Rename a file and all + -- Wrapper to content_item__rename + -- + file_id in cr_items.item_id%TYPE, + name in cr_items.name%TYPE + ) + is + begin + content_item.rename( + item_id => file_storage.rename_file.file_id, + name => file_storage.rename_file.name + ); + end rename_file; + + function copy_file( + -- + -- Copy a file, but only copy the live_revision + -- + file_id in cr_items.item_id%TYPE, + target_folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_revisions.revision_id%TYPE + is + v_name cr_items.name%TYPE; + v_live_revision cr_items.live_revision%TYPE; + v_filename cr_revisions.title%TYPE; + v_description cr_revisions.description%TYPE; + v_mime_type cr_revisions.mime_type%TYPE; + v_content_length cr_revisions.content_length%TYPE; + v_lob cr_revisions.content%TYPE; + v_file_path cr_revisions.filename%TYPE; + v_new_file_id cr_items.item_id%TYPE; + v_new_version_id cr_revisions.revision_id%TYPE; + v_indb_p char; + begin + -- We copy only the title from the file being copied, and attributes of the + -- live revision + select i.name, i.live_revision, r.title, r.description, + r.mime_type, r.content, r.filename, r.content_length, + decode(i.storage_type,'lob','t','f') + into v_name, v_live_revision, v_filename, v_description, + v_mime_type, v_lob, v_file_path, v_content_length, + v_indb_p + from cr_items i, cr_revisions r + where r.item_id = i.item_id + and r.revision_id = i.live_revision + and i.item_id = file_storage.copy_file.file_id; + + -- We should probably use the copy functions of CR + -- when we optimize this function + v_new_file_id := file_storage.new_file( + name => v_name, + folder_id => file_storage.copy_file.target_folder_id, + creation_user => file_storage.copy_file.creation_user, + creation_ip => file_storage.copy_file.creation_ip, + indb_p => v_indb_p + ); + + v_new_version_id := file_storage.new_version( + filename => v_filename, + description => v_description, + mime_type => v_mime_type, + item_id => v_new_file_id, + creation_user => file_storage.copy_file.creation_user, + creation_ip => file_storage.copy_file.creation_ip + ); + + -- Oracle is easier, since lobs are true lobs + -- For now, we simply copy the file name + update cr_revisions + set filename = v_file_path, + content = v_lob, + content_length = v_content_length + where revision_id = v_new_version_id; + + acs_object.update_last_modified(file_storage.copy_file.target_folder_id,file_storage.copy_file.creation_user,file_storage.copy_file.creation_ip); + + return v_new_version_id; + end copy_file; + + procedure move_file( + -- + -- Move a file, and all its versions, to a new folder + -- + file_id in cr_items.item_id%TYPE, + target_folder_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) + is + begin + content_item.move( + item_id => file_storage.move_file.file_id, + target_folder_id => file_storage.move_file.target_folder_id + ); + + acs_object.update_last_modified(file_storage.move_file.target_folder_id,file_storage.move_file.creation_user,file_storage.move_file.creation_ip); + + end; + + function new_version( + -- + -- Create a new version of a file + -- Wrapper for content_revision.new + -- + filename in cr_revisions.title%TYPE, + description in cr_revisions.description%TYPE, + mime_type in cr_revisions.mime_type%TYPE, + item_id in cr_items.item_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_revisions.revision_id%TYPE + is + v_revision_id cr_revisions.revision_id%TYPE; + v_folder_id cr_items.parent_id%TYPE; + begin + -- Create a revision + v_revision_id := content_revision.new( + title => new_version.filename, + description => new_version.description, + mime_type => new_version.mime_type, + item_id => new_version.item_id, + creation_user => new_version.creation_user, + creation_ip => new_version.creation_ip + ); + + -- Make live the newly created revision + content_item.set_live_revision(revision_id => v_revision_id); + + select cr_items.parent_id + into v_folder_id + from cr_items + where cr_items.item_id = file_storage.new_version.item_id; + + acs_object.update_last_modified(v_folder_id,new_version.creation_user,new_version.creation_ip); + acs_object.update_last_modified(new_version.item_id,new_version.creation_user,new_version.creation_ip); + + return v_revision_id; + + exception when NO_DATA_FOUND then + return v_revision_id; + end new_version; + + function get_title( + -- + item_id in cr_items.item_id%TYPE + ) return varchar + is + v_title cr_revisions.title%TYPE; + v_content_type cr_items.content_type%TYPE; + begin + select content_type + into v_content_type + from cr_items + where item_id = get_title.item_id; + + if v_content_type = 'content_folder' + then + select label + into v_title + from cr_folders + where folder_id = get_title.item_id; + else if v_content_type = 'content_symlink' + then + select label into v_title + from cr_symlinks + where symlink_id = get_title.item_id; + else + select title into v_title + from cr_revisions, cr_items + where item_id = get_title.item_id + and live_revision = revision_id; + end if; + end if; + + return v_title; + end get_title; + + function get_parent_id( + item_id in cr_items.item_id%TYPE + ) return cr_items.item_id%TYPE + is + v_parent_id cr_items.item_id%TYPE; + begin + select parent_id + into v_parent_id + from cr_items + where item_id = get_parent_id.item_id; + + return v_parent_id; + end get_parent_id; + + function get_content_type( + -- + -- Wrapper for content_item. get_content_type + -- + item_id in cr_items.item_id%TYPE + ) return cr_items.content_type%TYPE + is + v_content_type cr_items.content_type%TYPE; + begin + v_content_type := content_item.get_content_type( + item_id => file_storage.get_content_type.item_id + ); + + return v_content_type; + end get_content_type; + + function get_folder_name( + -- + -- Wrapper for content_folder.get_label + -- + folder_id in cr_folders.folder_id%TYPE + ) return cr_folders.label%TYPE + is + v_folder_name cr_folders.label%TYPE; + begin + v_folder_name := content_folder.get_label( + folder_id => file_storage.get_folder_name.folder_id + ); + + return v_folder_name; + end get_folder_name; + + function delete_version( + -- + -- Delete a version of a file + -- + file_id in cr_items.item_id%TYPE, + version_id in cr_revisions.revision_id%TYPE + ) return cr_items.parent_id%TYPE + is + v_parent_id cr_items.parent_id%TYPE; + begin + if file_storage.delete_version.version_id = content_item.get_live_revision(file_storage.delete_version.file_id) + then + content_revision.delete(file_storage.delete_version.version_id); + content_item.set_live_revision( + content_item.get_latest_revision(file_storage.delete_version.file_id) + ); + else + content_revision.delete(file_storage.delete_version.version_id); + end if; + + -- If the live revision is null, we have deleted the last version above + select decode(live_revision, null, parent_id, 0) + into v_parent_id + from cr_items + where item_id = file_storage.delete_version.file_id; + + -- Unfortunately, due to PostgreSQL behavior with regards referential integrity, + -- we cannot delete the content_item entry if there are no more revisions. + return v_parent_id; + end delete_version; + + function new_folder( + -- + -- Create a folder + -- + name in cr_items.name%TYPE, + folder_name in cr_folders.label%TYPE, + parent_id in cr_items.parent_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) return cr_folders.folder_id%TYPE + is + v_folder_id cr_folders.folder_id%TYPE; + begin + -- Create a new folder + v_folder_id := content_folder.new( + name => file_storage.new_folder.name, + label => file_storage.new_folder.folder_name, + parent_id => file_storage.new_folder.parent_id, + creation_user => file_storage.new_folder.creation_user, + creation_ip => file_storage.new_folder.creation_ip + ); + + -- register the standard content types + content_folder.register_content_type( + v_folder_id, -- folder_id + 'content_revision', -- content_type + 't' -- include_subtypes + ); + + content_folder.register_content_type( + v_folder_id, -- folder_id + 'content_folder', -- content_type + 't' -- include_subtypes + ); + + content_folder.register_content_type( + v_folder_id, -- folder_id + 'content_extlink', -- content_type + 't' -- include_subtypes + ); + + content_folder.register_content_type( + v_folder_id, -- folder_id + 'content_symlink', -- content_type + 't' -- include_subtypes + ); + + -- Give the creator admin privileges on the folder + acs_permission.grant_permission( + v_folder_id, -- object_id + file_storage.new_folder.creation_user, -- grantee_id + 'admin' -- privilege + ); + + return v_folder_id; + end new_folder; + + procedure delete_folder( + -- + -- Delete a folder + -- + folder_id in cr_folders.folder_id%TYPE + ) + is + begin + content_folder.delete( + folder_id => file_storage.delete_folder.folder_id + ); + end delete_folder; + +end file_storage; +/ +show errors; + +-- JS: BEFORE DELETE TRIGGER to clean up CR +create or replace trigger fs_package_items_delete_trig +before delete on fs_root_folders +for each row +declare + cursor v_cursor is + select item_id,content_type + from cr_items + where item_id != :old.folder_id + connect by parent_id = prior item_id + start with item_id = :old.folder_id + order by level desc; +begin + for v_rec in v_cursor + loop + -- We delete the item. On delete cascade should take care + -- of deletion of revisions. + if v_rec.content_type = 'file_storage_object' + then + content_item.delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = 'content_folder' + then + content_folder.delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = 'content_symlink' + then + content_symlink.delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = 'content_extlink' + then + content_extlink.delete(v_rec.item_id); + end if; + + end loop; +end; +/ +show errors; + +begin + for v_item_row in ( + select r.item_id, r.revision_id, r.title, i.name + from cr_items i, cr_revisions r + where i.item_id=r.item_id + and i.live_revision=r.revision_id + and i.content_type='file_storage_object' + ) loop + + update cr_items set name=v_item_row.name + where item_id=v_item_row.item_id; + + update cr_revisions set title=v_item_row.title + where revision_id=v_item_row.revision_id; + + end loop; + +end; +/ +show errors; + + +select inline_0(); + +drop function inline_0(); Index: openacs-4/packages/file-storage/sql/postgresql/file-storage-package-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/sql/postgresql/file-storage-package-create.sql,v diff -u -N -r1.8.2.6 -r1.8.2.7 --- openacs-4/packages/file-storage/sql/postgresql/file-storage-package-create.sql 15 Nov 2003 18:17:12 -0000 1.8.2.6 +++ openacs-4/packages/file-storage/sql/postgresql/file-storage-package-create.sql 15 Nov 2003 18:47:25 -0000 1.8.2.7 @@ -429,14 +429,11 @@ create or replace function file_storage__get_title ( -- - -- Unfortunately, title in the file-storage context refers - -- to the name attribute in cr_items, not the title attribute in - -- cr_revisions integer -- cr_items.item_id%TYPE ) returns varchar as ' declare get_title__item_id alias for $1; - v_title cr_items.name%TYPE; + v_title cr_revisions.title%TYPE; v_content_type cr_items.content_type%TYPE; begin @@ -455,8 +452,9 @@ where symlink_id = get_title__item_id; else select title into v_title - from cr_revisions - where revision_id=(select live_revision from cr_items where item_id = get_title__item_id); + from cr_revisions, cr_items + where revision_id=live_revision + and item_id=get_title__item_id; end if; end if; @@ -559,7 +557,7 @@ where cr_items.item_id = new_version__item_id; perform acs_object__update_last_modified(v_folder_id,new_version__creation_user,new_version__creation_ip); - + perform acs_object__update_last_modified(new_version__item_id,new_version__creation_user,new_version__creation_ip); return v_revision_id; end;' language 'plpgsql'; Index: openacs-4/packages/file-storage/sql/postgresql/upgrade/upgrade-4.6.3-4.8.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/sql/postgresql/upgrade/Attic/upgrade-4.6.3-4.8.sql,v diff -u -N -r1.1.2.1 -r1.1.2.2 --- openacs-4/packages/file-storage/sql/postgresql/upgrade/upgrade-4.6.3-4.8.sql 15 Nov 2003 18:31:02 -0000 1.1.2.1 +++ openacs-4/packages/file-storage/sql/postgresql/upgrade/upgrade-4.6.3-4.8.sql 15 Nov 2003 18:47:25 -0000 1.1.2.2 @@ -1,5 +1,161 @@ -- $Id +create or replace function file_storage__get_root_folder ( + -- + -- Returns the root folder corresponding to a particular + -- package instance. + -- + integer -- apm_packages.package_id%TYPE +) +returns integer as ' -- fs_root_folders.folder_id%TYPE +declare + get_root_folder__package_id alias for $1; + v_folder_id fs_root_folders.folder_id%TYPE; + v_count integer; +begin + + select count(*) into v_count + from fs_root_folders + where package_id = get_root_folder__package_id; + + if v_count > 0 then + select folder_id into v_folder_id + from fs_root_folders + where package_id = get_root_folder__package_id; + else + -- must be a new instance. Gotta create a new root folder + v_folder_id := file_storage__new_root_folder(get_root_folder__package_id, null, null); + end if; + + return v_folder_id; + +end;' language 'plpgsql' with (iscachable); + +create or replace function file_storage__get_package_id ( + integer -- cr_items.item_id%TYPE +) returns integer as ' -- fs_root_folders.package_id%TYPE +declare + get_package_id__item_id alias for $1; + v_package_id fs_root_folders.package_id%TYPE; + v_tree_sortkey cr_items.tree_sortkey%TYPE; +begin + + select fs_root_folders.package_id + into v_package_id + from fs_root_folders, + (select cr_items.item_id + from (select tree_ancestor_keys(cr_items_get_tree_sortkey(get_package_id__item_id)) as tree_sortkey) parents, + cr_items + where cr_items.tree_sortkey = parents.tree_sortkey) this + where fs_root_folders.folder_id = this.item_id; + + if NOT FOUND then + return null; + else + return v_package_id; + end if; + +end;' language 'plpgsql' with (iscachable); + +create or replace function file_storage__new_root_folder ( + -- + -- Creates a new root folder + -- + -- + -- A hackish function to get around the fact that we can not run + -- code automatically when a new package instance is created. + -- + integer, -- apm_packages.package_id%TYPE + varchar, -- cr_folders.label%TYPE + varchar, -- cr_folders.description%TYPE + varchar -- cr_items.name%TYPE +) +returns integer as ' -- fs_root_folders.folder_id%TYPE +declare + new_root_folder__package_id alias for $1; + new_root_folder__folder_name alias for $2; + new_root_folder__description alias for $3; + new_root_folder__url alias for $4; + v_folder_id fs_root_folders.folder_id%TYPE; + v_package_name apm_packages.instance_name%TYPE; + v_package_key apm_packages.package_key%TYPE; + v_folder_name cr_folders.label%TYPE; + v_description cr_folders.description%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; + + if new_root_folder__folder_name is null + then + v_folder_name := v_package_name || '' Root Folder ''; + else + v_folder_name := new_root_folder__folder_name; + end if; + + if new_root_folder__description is null + then + v_description := ''Root folder for the file-storage system. All other folders in file storage are subfolders of this one.''; + else + v_description := new_root_folder__description; + end if; + + v_folder_id := content_folder__new ( + coalesce (new_root_folder__url, v_package_key || ''_'' || new_root_folder__package_id), -- name + v_folder_name, -- label + v_description, -- description + null -- parent_id (default) + ); + + insert into fs_root_folders + (package_id, folder_id) + values + (new_root_folder__package_id, v_folder_id); + + -- allow child items to be added + -- JS: Note that we need to set include_subtypes to + -- JS: true since we created a new subtype. + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_revision'', -- content_types + ''t'' -- include_subtypes + ); + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_folder'', -- content_types + ''t'' -- include_subtypes + ); + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_symlink'', -- content_types + ''t'' -- include_subtypes + ); + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_extlink'', -- content_types + ''t'' -- include_subtypes + ); + + -- set up default permissions + PERFORM acs_permission__grant_permission ( + v_folder_id, -- object_id + acs__magic_object_id(''the_public''), -- grantee_id + ''read'' -- privilege + ); + + PERFORM acs_permission__grant_permission ( + v_folder_id, -- object_id + acs__magic_object_id(''registered_users''), -- grantee_id + ''write'' -- privilege + ); + + return v_folder_id; + +end;' language 'plpgsql'; + + create or replace function file_storage__new_file( -- -- Create a file in CR in preparation for actual storage @@ -15,7 +171,7 @@ integer -- cr_items.item_id%TYPE, ) returns integer as ' -- cr_items.item_id%TYPE declare - new_file__title alias for $1; + new_file__name alias for $1; new_file__folder_id alias for $2; new_file__user_id alias for $3; new_file__creation_ip alias for $4; @@ -27,7 +183,7 @@ if new_file__indb_p then v_item_id := content_item__new ( - new_file__title, -- name + new_file__name, -- name new_file__folder_id, -- parent_id new_file__item_id, -- item_id (default) null, -- locale (default) @@ -45,7 +201,7 @@ ); else v_item_id := content_item__new ( - new_file__title, -- name + new_file__name, -- name new_file__folder_id, -- parent_id new_file__item_id, -- item_id (default) null, -- locale (default) @@ -72,6 +228,71 @@ end;' language 'plpgsql'; +create or replace function file_storage__new_file( + varchar, -- cr_items.name%TYPE, + integer, -- cr_items.parent_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar, -- acs_objects.creation_ip%TYPE, + boolean -- store in db? +) returns integer as ' -- cr_items.item_id%TYPE +declare + new_file__name alias for $1; + new_file__folder_id alias for $2; + new_file__user_id alias for $3; + new_file__creation_ip alias for $4; + new_file__indb_p alias for $5; +begin + + return file_storage__new_file( + new_file__name, + new_file__folder_id, + new_file__user_id, + new_file__creation_ip, + new_file__indb_p, + null + ); + +end;' language 'plpgsql'; + + +create or replace function file_storage__delete_file ( + -- + -- Delete a file and all its version + -- Wrapper to content_item__delete + -- + integer -- cr_items.item_id%TYPE +) returns integer as ' +declare + delete_file__file_id alias for $1; +begin + + return content_item__delete(delete_file__file_id); + +end;' language 'plpgsql'; + + +create or replace function file_storage__rename_file ( + -- + -- Rename a file and all + -- Wrapper to content_item__rename + -- + integer, -- cr_items.item_id%TYPE, + varchar -- cr_items.name%TYPE +) returns integer as ' +declare + rename_file__file_id alias for $1; + rename_file__name alias for $2; + +begin + + return content_item__rename( + rename_file__file_id, -- item_id + rename_file__name -- name + ); + +end;' language 'plpgsql'; + + create or replace function file_storage__copy_file( -- -- Copy a file, but only copy the live_revision @@ -86,7 +307,7 @@ copy_file__target_folder_id alias for $2; copy_file__creation_user alias for $3; copy_file__creation_ip alias for $4; - v_title cr_items.name%TYPE; + v_name cr_items.name%TYPE; v_live_revision cr_items.live_revision%TYPE; v_filename cr_revisions.title%TYPE; v_description cr_revisions.description%TYPE; @@ -106,24 +327,438 @@ (case when i.storage_type = ''lob'' then true else false + end) + into v_name,v_live_revision,v_filename,v_description,v_mime_type,v_content_length,v_indb_p + from cr_items i, cr_revisions r + where r.item_id = i.item_id + and r.revision_id = i.live_revision + and i.item_id = copy_file__file_id; + -- We should probably use the copy functions of CR + -- when we optimize this function + v_new_file_id := file_storage__new_file( + v_name, -- name + copy_file__target_folder_id, -- folder_id + copy_file__creation_user, -- creation_user + copy_file__creation_ip, -- creation_ip + v_indb_p -- indb_p + ); + + v_new_version_id := file_storage__new_version ( + v_filename, -- title + v_description, -- description + v_mime_type, -- mime_type + v_new_file_id, -- item_id + copy_file__creation_user, -- creation_user + copy_file__creation_ip -- creation_ip + ); + + if v_indb_p + then + + -- Lob to copy from + select lob into v_lob_id + from cr_revisions + where revision_id = v_live_revision; + + -- New lob id + v_new_lob_id := empty_lob(); + + -- copy the blob + perform lob_copy(v_lob_id,v_new_lob_id); + + -- Update the lob id on the new version + update cr_revisions + set lob = v_new_lob_id, + content_length = v_content_length + where revision_id = v_new_version_id; + + else + + -- For now, we simply copy the file name + select content into v_file_path + from cr_revisions + where revision_id = v_live_revision; + + -- Update the file path + update cr_revisions + set content = v_file_path, + content_length = v_content_length + where revision_id = v_new_version_id; + + end if; + + perform acs_object__update_last_modified(copy_file__target_folder_id,copy_file__creation_user,copy_file__creation_ip); + + return v_new_version_id; + +end;' language 'plpgsql'; + + +create or replace function file_storage__move_file ( + -- + -- Move a file (ans all its versions) to a different folder. + -- Wrapper for content_item__move + -- + integer, -- cr_folders.folder_id%TYPE, + integer -- cr_folders.folder_id%TYPE +) returns integer as ' -- 0 for success +declare + move_file__file_id alias for $1; + move_file__target_folder_id alias for $2; + move_file__creation_user alias for $3; + move_file__creation_ip alias for $4; +begin + + perform content_item__move( + move_file__file_id, -- item_id + move_file__target_folder_id -- target_folder_id + ); + + perform acs_object__update_last_modified(move_file__target_folder_id,move_file__creation_user,move_file__creation_ip); + + return 0; +end;' language 'plpgsql'; + + +create or replace function file_storage__get_title ( + -- + integer -- cr_items.item_id%TYPE +) returns varchar as ' +declare + get_title__item_id alias for $1; + v_title cr_revisions.title%TYPE; + v_content_type cr_items.content_type%TYPE; +begin + + select content_type into v_content_type + from cr_items + where item_id = get_title__item_id; + + if v_content_type = ''content_folder'' + then + select label into v_title + from cr_folders + where folder_id = get_title__item_id; + else if v_content_type = ''content_symlink'' + then + select label into v_title from cr_symlinks + where symlink_id = get_title__item_id; + else + select title into v_title + from cr_revisions, cr_items + where revision_id=live_revision + and item_id=get_title__item_id; + end if; + end if; + + return v_title; + +end;' language 'plpgsql'; + +create or replace function file_storage__get_parent_id ( + integer -- item_id in cr_items.item_id%TYPE + ) returns integer as ' -- cr_items.item_id%TYPE + declare + get_parent_id__item_id alias for $1; + v_parent_id cr_items.item_id%TYPE; + begin + + select parent_id + into v_parent_id + from cr_items + where item_id = get_parent_id__item_id; + + return v_parent_id; + +end;'language 'plpgsql'; + + +create or replace function file_storage__get_content_type ( + -- + -- Wrapper for content_item__get_content_type + integer -- cr_items.item_id%TYPE +) returns varchar as ' -- cr_items.content_type%TYPE +declare + get_content_type__file_id alias for $1; +begin + return content_item__get_content_type( + get_content_type__file_id + ); + +end;' language 'plpgsql'; + + + +create or replace function file_storage__get_folder_name ( + -- + -- Wrapper for content_folder__get_label + integer -- cr_folders.folder_id%TYPE +) returns varchar as ' -- cr_folders.label%TYPE +declare + get_folder_name__folder_id alias for $1; +begin + return content_folder__get_label( + get_folder_name__folder_id + ); + +end;' language 'plpgsql'; + + +create or replace function file_storage__new_version ( + -- + -- Create a new version of a file + -- Wrapper for content_revision__new + -- + varchar, -- cr_revisions.title%TYPE, + varchar, -- cr_revisions.description%TYPE, + varchar, -- cr_revisions.mime_type%TYPE, + integer, -- cr_items.item_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar -- acs_objects.creation_ip%TYPE +) returns integer as ' -- cr_revisions.revision_id +declare + new_version__filename alias for $1; + new_version__description alias for $2; + new_version__mime_type alias for $3; + new_version__item_id alias for $4; + new_version__creation_user alias for $5; + new_version__creation_ip alias for $6; + v_revision_id cr_revisions.revision_id%TYPE; + v_folder_id cr_items.parent_id%TYPE; +begin + -- Create a revision + v_revision_id := content_revision__new ( + new_version__filename, -- title + new_version__description, -- description + now(), -- publish_date + new_version__mime_type, -- mime_type + null, -- nls_language + null, -- data (default) + new_version__item_id, -- item_id + null, -- revision_id + now(), -- creation_date + new_version__creation_user, -- creation_user + new_version__creation_ip -- creation_ip + ); + + -- Make live the newly created revision + perform content_item__set_live_revision(v_revision_id); + + select cr_items.parent_id + into v_folder_id + from cr_items + where cr_items.item_id = new_version__item_id; + + perform acs_object__update_last_modified(v_folder_id,new_version__creation_user,new_version__creation_ip); + perform acs_object__update_last_modified(new_version__item_id,new_version__creation_user,new_version__creation_ip); + return v_revision_id; + +end;' language 'plpgsql'; + + +create or replace function file_storage__delete_version ( + -- + -- Delete a version of a file + -- + integer, -- cr_items.item_id%TYPE, + integer -- cr_revisions.revision_id%TYPE +) returns integer as ' -- cr_items.parent_id%TYPE +declare + delete_version__file_id alias for $1; + delete_version__version_id alias for $2; + v_parent_id cr_items.parent_id%TYPE; + v_deleted_last_version_p boolean; +begin + + if delete_version__version_id = content_item__get_live_revision(delete_version__file_id) + then + PERFORM content_revision__delete(delete_version__version_id); + PERFORM content_item__set_live_revision( + content_item__get_latest_revision(delete_version__file_id) + ); + else + PERFORM content_revision__delete(delete_version__version_id); + end if; + + -- If the live revision is null, we have deleted the last version above + select (case when live_revision is null + then parent_id + else 0 + end) + into v_parent_id + from cr_items + where item_id = delete_version__file_id; + + -- Unfortunately, due to PostgreSQL behavior with regards referential integrity, + -- we cannot delete the content_item entry if there are no more revisions. + return v_parent_id; + +end;' language 'plpgsql'; + + +create or replace function file_storage__new_folder( + -- + -- Create a folder + -- + varchar, -- cr_items.name%TYPE, + varchar, -- cr_folders.label%TYPE, + integer, -- cr_items.parent_id%TYPE, + integer, -- acs_objects.creation_user%TYPE, + varchar -- acs_objects.creation_ip%TYPE +) returns integer as ' -- cr_folders.folder_id%TYPE +declare + new_folder__name alias for $1; + new_folder__folder_name alias for $2; + new_folder__parent_id alias for $3; + new_folder__creation_user alias for $4; + new_folder__creation_ip alias for $5; + v_folder_id cr_folders.folder_id%TYPE; +begin + + -- Create a new folder + v_folder_id := content_folder__new ( + new_folder__name, -- name + new_folder__folder_name, -- label + null, -- description + new_folder__parent_id, -- parent_id + null, -- context_id (default) + null, -- folder_id (default) + now(), -- creation_date + new_folder__creation_user, -- creation_user + new_folder__creation_ip -- creation_ip + ); + + -- register the standard content types + -- JS: Note that we need to set include_subtypes + -- JS: to true since we created a new subtype. + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_revision'', -- content_type + ''t''); -- include_subtypes (default) + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_folder'', -- content_type + ''t'' -- include_subtypes (default) + ); + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_extlink'', -- content_types + ''t'' -- include_subtypes + ); + + PERFORM content_folder__register_content_type( + v_folder_id, -- folder_id + ''content_symlink'', -- content_types + ''t'' -- include_subtypes + ); + + -- Give the creator admin privileges on the folder + PERFORM acs_permission__grant_permission ( + v_folder_id, -- object_id + new_folder__creation_user, -- grantee_id + ''admin'' -- privilege + ); + + return v_folder_id; + +end;' language 'plpgsql'; + + +create or replace function file_storage__delete_folder( + -- + -- Delete a folder + -- + integer -- cr_folders.folder_id%TYPE +) returns integer as ' -- 0 for success +declare + delete_folder__folder_id alias for $1; +begin + + return content_folder__delete( + delete_folder__folder_id -- folder_id + ); + +end;' language 'plpgsql'; + + +-- JS: BEFORE DELETE TRIGGER to clean up CR entries (except root folder) +create or replace function fs_package_items_delete_trig () returns opaque as ' +declare + + v_rec record; +begin + + for v_rec in + + -- We want to delete all cr_items entries, starting from the leaves all + -- the way up the root folder (old.folder_id). + select c1.item_id, c1.content_type + from cr_items c1, cr_items c2 + where c2.item_id = old.folder_id + and c1.tree_sortkey between c2.tree_sortkey and tree_right(c2.tree_sortkey) + and c1.item_id <> old.folder_id + order by c1.tree_sortkey desc + loop + + -- DRB: Why can''t we just use object delete here? + + + -- We delete the item. On delete cascade should take care + -- of deletion of revisions. + if v_rec.content_type = ''file_storage_object'' + then + raise notice ''Deleting item_id = %'',v_rec.item_id; + PERFORM content_item__delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = ''content_folder'' + then + raise notice ''Deleting folder_id = %'',v_rec.item_id; + PERFORM content_folder__delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = ''content_symlink'' + then + raise notice ''Deleting symlink_id = %'',v_rec.item_id; + PERFORM content_symlink__delete(v_rec.item_id); + end if; + + -- Instead of doing an if-else, we make sure we are deleting a folder. + if v_rec.content_type = ''content_extlink'' + then + raise notice ''Deleting folder_id = %'',v_rec.item_id; + PERFORM content_extlink__delete(v_rec.item_id); + end if; + + end loop; + + -- We need to return something for the trigger to be activated + return old; + +end;' language 'plpgsql'; + create function inline_0 () returns integer as ' declare v_item_row record; begin for v_item_row in select - r.item_id, r.revision_id, i.live_revision + r.item_id, r.revision_id, r.title, i.name, i.live_revision from cr_items i, cr_revisions r where i.item_id=r.item_id and i.live_revision=r.revision_id and i.content_type=''file_storage_object''; loop - update cr_items set name=v_row.name - where item_id=v_row.item_id; + update cr_items set name=v_item_row.name + where item_id=v_item_row.item_id; - update cr_revisions set title=v_row.title - where revision_id=p_revision_id; + update cr_revisions set title=v_item_row.title + where revision_id=v_item_row.revision_id; end loop; Index: openacs-4/packages/file-storage/tcl/file-storage-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/tcl/file-storage-procs.tcl,v diff -u -N -r1.25.2.8 -r1.25.2.9 --- openacs-4/packages/file-storage/tcl/file-storage-procs.tcl 15 Nov 2003 18:17:12 -0000 1.25.2.8 +++ openacs-4/packages/file-storage/tcl/file-storage-procs.tcl 15 Nov 2003 18:47:25 -0000 1.25.2.9 @@ -640,6 +640,10 @@ db_transaction { if {[empty_string_p $item_id] || ![db_string item_exists ""]} { set item_id [db_exec_plsql create_item ""] + + if {![empty_string_p $creation_user]} { + permission::grant -party_id $creation_user -object_id $item_id -privilege admin + } } set revision_id [cr_import_content \ @@ -659,9 +663,6 @@ db_dml set_live_revision "" db_exec_plsql update_last_modified "" - if {![empty_string_p $creation_user]} { - permission::grant -party_id $creation_user -object_id $item_id -privilege admin - } } on_error { error $errmsg } Index: openacs-4/packages/file-storage/www/file-add-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/www/Attic/file-add-2-postgresql.xql,v diff -u -N --- openacs-4/packages/file-storage/www/file-add-2-postgresql.xql 9 Nov 2003 03:36:56 -0000 1.5.2.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,82 +0,0 @@ - - - - postgresql7.1 - - - - select file_storage__new_file ( - :filename, -- filename - :folder_id, -- parent_id - :user_id, -- creation_user - :creation_ip, -- creation_ip - true -- indb_p - ); - - - - - - select file_storage__new_file ( - :filename, -- filename - :folder_id, -- parent_id - :user_id, -- creation_user - :creation_ip, -- creation_ip - false -- indb_p - ); - - - - - - - - select file_storage__new_version ( - :title, -- title - :description, -- description - :mime_type, -- mime_type - :file_id, -- item_id - :user_id, -- creation_user - :creation_ip -- creation_ip - ); - - - - - - - - - update cr_revisions - set lob = [set __lob_id [db_string get_lob_id "select empty_lob()"]] - where revision_id = :version_id - - - - - - - - update cr_revisions - set content_length = lob_length(lob) - where revision_id = :version_id - - - - - - - - - - update cr_revisions - set content = '$tmp_filename', - content_length = $tmp_size - where revision_id = :version_id - - - - - - - Index: openacs-4/packages/file-storage/www/file-add-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/www/Attic/file-add-2.tcl,v diff -u -N --- openacs-4/packages/file-storage/www/file-add-2.tcl 18 Mar 2003 20:32:14 -0000 1.6.2.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,108 +0,0 @@ -ad_page_contract { - script to recieve the new file and insert it into the database - - @author Kevin Scaldeferri (kevin@arsdigita.com) - @creation-date 6 Nov 2000 - @cvs-id $Id: file-add-2.tcl,v 1.6.2.2 2003/03/18 20:32:14 donb Exp $ -} { - folder_id:integer,notnull - upload_file:notnull,trim - upload_file.tmpfile:tmpfile - title:notnull,trim - description -} -validate { - valid_folder -requires {folder_id:integer} { - if ![fs_folder_p $folder_id] { - ad_complain "The specified parent folder is not valid." - } - } - - max_size -requires {upload_file} { - set n_bytes [file size ${upload_file.tmpfile}] - set max_bytes [ad_parameter "MaximumFileSize"] - if { $n_bytes > $max_bytes } { - ad_complain "Your file is larger than the maximum file size allowed on this system ([util_commify_number $max_bytes] bytes)" - } - } -} - -# Check for write permission on this folder -ad_require_permission $folder_id write - -# Get the filename part of the upload file -if ![regexp {[^//\\]+$} $upload_file filename] { - # no match - set filename $upload_file -} - -# Get the user -set user_id [ad_conn user_id] - -# Get the ip -set creation_ip [ad_conn peeraddr] - -set mime_type [cr_filename_to_mime_type -create $upload_file] - -# Get the storage type -set indb_p [ad_parameter "StoreFilesInDatabaseP" -package_id [ad_conn package_id]] - -db_transaction { - - # create the new item - if {$indb_p} { - - set file_id [db_exec_plsql new_lob_file {}] - - set version_id [db_exec_plsql new_version {}] - - db_dml lob_content {} -blob_files [list ${upload_file.tmpfile}] - - - # Unfortunately, we can only calculate the file size after the lob is uploaded - db_dml lob_size {} - - } else { - - set file_id [db_exec_plsql new_fs_file {}] - - - set version_id [db_exec_plsql new_version {}] - - set tmp_filename [cr_create_content_file $file_id $version_id ${upload_file.tmpfile}] - set tmp_size [cr_file_size $tmp_filename] - - db_dml fs_content_size {} - - } - - # We know the user has write permission to this folder, but they may not have admin privileges. - # They should always be able to admin their own file by default, so they can delete it, control - # who can read it, etc. - - if { [string is false [permission::permission_p -party_id $user_id -object_id $folder_id -privilege admin]] } { - permission::grant -party_id $user_id -object_id $file_id -privilege admin - } - -} on_error { - - # most likely a duplicate name or a double click - -# if [db_string duplicate_check " -# select count(*) -# from cr_items -# where name = :filename -# and parent_id = :folder_id"] { -# ad_return_complaint 1 "Either there is already a file with the name \"$tmp_filename\" or you clicked on the button more than once. You can use the Back button to return and choose a new name, or return to the directory listing to see if your file 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_return_complaint 1 "You probably clicked on the Add button more than once. Check if the file is in the folder, or you can use the Back button to return and re-enter the version file." - - ad_script_abort -} - - -ad_returnredirect "?folder_id=$folder_id" Index: openacs-4/packages/file-storage/www/file-add-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/www/Attic/file-add-2.xql,v diff -u -N --- openacs-4/packages/file-storage/www/file-add-2.xql 16 Aug 2001 20:27:37 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,17 +0,0 @@ - - - - - - - select count(*) - from cr_items - where name = :filename - and parent_id = :folder_id - - - - - - -