-- 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);