-- Data model to support content repository of the ArsDigita -- Community System -- Copyright (C) 1999-2000 ArsDigita Corporation -- Author: Karl Goldstein (karlg@arsdigita.com) -- $Id: content-symlink.sql,v 1.21 2011/07/07 10:46:02 gustafn 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 or replace package body content_symlink -- function new -- old define_function_args('content_symlink__new','name,label,target_id,parent_id,symlink_id,creation_date;now,creation_user,creation_ip,package_id') -- new select define_function_args('content_symlink__new','name;null,label;null,target_id,parent_id,symlink_id;null,creation_date;now,creation_user;null,creation_ip;null,package_id;null'); -- -- procedure content_symlink__new/9 -- CREATE OR REPLACE FUNCTION content_symlink__new( new__name varchar, -- default null new__label varchar, -- default null new__target_id integer, new__parent_id integer, new__symlink_id integer, -- default null new__creation_date timestamptz, -- default now() -- default 'now' new__creation_user integer, -- default null new__creation_ip varchar, -- default null new__package_id integer -- default null ) RETURNS integer AS $$ DECLARE v_symlink_id cr_symlinks.symlink_id%TYPE; v_package_id acs_objects.package_id%TYPE; v_name cr_items.name%TYPE; v_label cr_symlinks.label%TYPE; v_ctype varchar; BEGIN -- SOME CHECKS -- -- 1) check that the target is now a symlink if content_symlink__is_symlink(new__target_id) = 't' then raise EXCEPTION '-20000: Cannot create a symlink to a symlink %', new__target_id; end if; -- 2) check that the parent is a folder if content_folder__is_folder(new__parent_id) = 'f' then raise EXCEPTION '-20000: The parent is not a folder'; end if; -- 3) check that parent folder supports symlinks if content_folder__is_registered(new__parent_id,'content_symlink','f') = 'f' then raise EXCEPTION '-20000: This folder does not allow symlinks to be created'; end if; -- 4) check that the content folder supports the target items content type if content_folder__is_registered(new__parent_id, content_item__get_content_type(new__target_id), 'f') = 'f' then v_ctype := content_item__get_content_type(new__target_id); raise EXCEPTION '-20000: This folder does not allow symlinks to items of type % to be created', v_ctype; end if; -- PASSED ALL CHECKS -- -- Select default name if the name is null if new__name is null or new__name = '' then select 'symlink_to_' || name into v_name from cr_items where item_id = new__target_id; if NOT FOUND then v_name := null; end if; else v_name := new__name; end if; -- Select default label if the label is null if new__label is null then v_label := 'Symlink to ' || v_name; else v_label := new__label; end if; if new__package_id is null then v_package_id := acs_object__package_id(new__parent_id); else v_package_id := new__package_id; end if; v_symlink_id := content_item__new( v_name, new__parent_id, new__symlink_id, null, new__creation_date, new__creation_user, null, new__creation_ip, 'content_item', 'content_symlink', null, null, 'text/plain', null, null, 'text', v_package_id ); insert into cr_symlinks (symlink_id, target_id, label) values (v_symlink_id, new__target_id, v_label); update acs_objects set title = v_label where object_id = v_symlink_id; return v_symlink_id; END; $$ LANGUAGE plpgsql; -- -- procedure content_symlink__new/8 -- CREATE OR REPLACE FUNCTION content_symlink__new( new__name varchar, -- default null new__label varchar, -- default null new__target_id integer, new__parent_id integer, new__symlink_id integer, -- default null new__creation_date timestamptz, -- default now() new__creation_user integer, -- default null new__creation_ip varchar -- default null ) RETURNS integer AS $$ -- -- content_symlink__new/8 maybe obsolete, when we define proper defaults for /9 -- DECLARE BEGIN return content_extlink__new(new__name, new__label, new__target_id, new__parent_id, new__symlink_id, new__creation_date, new__creation_user, new__creation_ip, null ); END; $$ LANGUAGE plpgsql; -- procedure delete select define_function_args('content_symlink__delete','symlink_id'); -- -- procedure content_symlink__delete/1 -- CREATE OR REPLACE FUNCTION content_symlink__delete( delete__symlink_id integer ) RETURNS integer AS $$ DECLARE BEGIN PERFORM content_symlink__del(delete__symlink_id); return 0; END; $$ LANGUAGE plpgsql; select define_function_args('content_symlink__del','symlink_id'); -- -- procedure content_symlink__del/1 -- CREATE OR REPLACE FUNCTION content_symlink__del( del__symlink_id integer ) RETURNS integer AS $$ DECLARE BEGIN delete from cr_symlinks where symlink_id = del__symlink_id; PERFORM content_item__delete(del__symlink_id); return 0; END; $$ LANGUAGE plpgsql; -- function is_symlink select define_function_args('content_symlink__is_symlink','item_id'); -- -- procedure content_symlink__is_symlink/1 -- CREATE OR REPLACE FUNCTION content_symlink__is_symlink( is_symlink__item_id integer ) RETURNS boolean AS $$ DECLARE v_symlink_p boolean; BEGIN select count(*) = 1 into v_symlink_p from cr_symlinks where symlink_id = is_symlink__item_id; return v_symlink_p; END; $$ LANGUAGE plpgsql stable; -- procedure copy -- old define_function_args('content_symlink__copy','symlink_id,target_folder_id,creation_user,creation_ip,name') -- new select define_function_args('content_symlink__copy','symlink_id,target_folder_id,creation_user,creation_ip;null,name;null'); -- -- procedure content_symlink__copy/5 -- CREATE OR REPLACE FUNCTION content_symlink__copy( copy__symlink_id integer, copy__target_folder_id integer, copy__creation_user integer, copy__creation_ip varchar, -- default null copy__name varchar -- default null ) RETURNS integer AS $$ DECLARE v_current_folder_id cr_folders.folder_id%TYPE; v_name cr_items.name%TYPE; v_target_id cr_items.item_id%TYPE; v_label cr_symlinks.label%TYPE; v_symlink_id cr_symlinks.symlink_id%TYPE; BEGIN -- XXX: bug if target is not a folder this will silently fail. if content_folder__is_folder(copy__target_folder_id) = 't' then select parent_id into v_current_folder_id from cr_items where item_id = copy__symlink_id; -- can't copy to the same folder unless name is different select i.name, content_symlink__resolve(i.item_id), s.label into v_name, v_target_id, v_label from cr_symlinks s, cr_items i where s.symlink_id = i.item_id and s.symlink_id = copy__symlink_id; -- copy to a different folder, or same folder if name -- is different if copy__target_folder_id != v_current_folder_id or ( v_name <> copy_name and copy_name is not null ) then if content_folder__is_registered(copy__target_folder_id, 'content_symlink','f') = 't' then if content_folder__is_registered(copy__target_folder_id, content_item__get_content_type(content_symlink__resolve(copy__symlink_id)),'f') = 't' then v_symlink_id := content_symlink__new( coalesce (copy__name,v_name), v_label, v_target_id, copy__target_folder_id, null, now(), copy__creation_user, copy__creation_ip, null ); end if; end if; end if; end if; return v_symlink_id; END; $$ LANGUAGE plpgsql; -- -- procedure content_symlink__copy/4 -- CREATE OR REPLACE FUNCTION content_symlink__copy( copy__symlink_id integer, copy__target_folder_id integer, copy__creation_user integer, copy__creation_ip varchar -- default null ) RETURNS integer AS $$ -- -- content_symlink__copy/4 maybe obsolete, when we define proper defaults for /5 -- DECLARE v_current_folder_id cr_folders.folder_id%TYPE; v_name cr_items.name%TYPE; v_target_id cr_items.item_id%TYPE; v_label cr_symlinks.label%TYPE; v_symlink_id cr_symlinks.symlink_id%TYPE; BEGIN v_symlink_id := content_symlink__copy ( copy__symlink_id, copy__target_folder_id, copy__creation_user, copy__creation_ip, NULL ); return v_symlink_id; END; $$ LANGUAGE plpgsql; -- function resolve select define_function_args('content_symlink__resolve','item_id'); -- -- procedure content_symlink__resolve/1 -- CREATE OR REPLACE FUNCTION content_symlink__resolve( resolve__item_id integer ) RETURNS integer AS $$ DECLARE v_target_id cr_items.item_id%TYPE; BEGIN select target_id into v_target_id from cr_symlinks where symlink_id = resolve__item_id; if NOT FOUND then return resolve__item_id; else return v_target_id; end if; END; $$ LANGUAGE plpgsql stable strict; -- function resolve_content_type select define_function_args('content_symlink__resolve_content_type','item_id'); -- -- procedure content_symlink__resolve_content_type/1 -- CREATE OR REPLACE FUNCTION content_symlink__resolve_content_type( resolve_content_type__item_id integer ) RETURNS varchar AS $$ DECLARE v_content_type cr_items.content_type%TYPE; BEGIN select content_item__get_content_type(target_id) into v_content_type from cr_symlinks where symlink_id = resolve_content_type__item_id; return v_content_type; END; $$ LANGUAGE plpgsql stable strict; -- show errors -- Convenience view to simply access to symlink targets create view cr_resolved_items as select i.parent_id, i.item_id, i.name, case when s.target_id is NULL then 'f' else 't' end as is_symlink, coalesce(s.target_id, i.item_id) as resolved_id, s.label from cr_items i left outer join cr_symlinks s on (i.item_id = s.symlink_id);