Notifications

by David Bell and Simon Carstensen

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

The notifications package allows you to send notifications through any defined communications medium (e.g. email, sms) upon some event occurring within the system.

This tutorial steps through the process of integrating the notifications package with your package.

First step is to create the notification types. To do this a script similar to the one below needs to be loaded into PostgreSQL. I create this script in a package-name/sql/postgresql/package-name-notifications-init.sql file. I then load this file from my create SQL file. The following code snippet is taken from Weblogger. It creates a lars_blogger_notif notification type (which was created above).

    create function inline_0() returns integer as $$
    declare
            impl_id integer;
            v_foo   integer;
    begin
        -- the notification type impl
        impl_id := acs_sc_impl__new (
                      'NotificationType',
                      'lars_blogger_notif_type',
                      'lars-blogger'
        );

        v_foo := acs_sc_impl_alias__new (
                    'NotificationType',
                    'lars_blogger_notif_type',
                    'GetURL',
                    'lars_blogger::notification::get_url',
                    'TCL'
        );

        v_foo := acs_sc_impl_alias__new (
                    'NotificationType',
                    'lars_blogger_notif_type',
                    'ProcessReply',
                    'lars_blogger::notification::process_reply',
                    'TCL'
        );

        PERFORM acs_sc_binding__new (
                    'NotificationType',
                    'lars_blogger_notif_type'
        );

        v_foo:= notification_type__new (
	        NULL,
                impl_id,
                'lars_blogger_notif',
                'Blog Notification',
                'Notifications for Blog',
		now(),
                NULL,
                NULL,
		NULL
        );

        -- enable the various intervals and delivery methods
        insert into notification_types_intervals
        (type_id, interval_id)
        select v_foo, interval_id
        from notification_intervals where name in ('instant','hourly','daily');

        insert into notification_types_del_methods
        (type_id, delivery_method_id)
        select v_foo, delivery_method_id
        from notification_delivery_methods where short_name in ('email');

        return (0);
    end;
    $$ language plpgsql;

    select inline_0();
    drop function inline_0();
    

You also need a drop script. This is untested for compatibility with the above script.

      -- @author gwong@orchardlabs.com,ben@openforce.biz
      -- @creation-date 2002-05-16
      --
      -- This code is newly concocted by Ben, but with significant concepts and code
      -- lifted from Gilbert's UBB forums. Thanks Orchard Labs.
      -- Lars and Jade in turn lifted this from gwong and ben.

create function inline_0 ()
returns integer as $$
declare
    row                             record;
begin
    for row in select nt.type_id
               from notification_types nt
               where nt.short_name in ('lars_blogger_notif_type','lars_blogger_notif')
    loop
        perform notification_type__delete(row.type_id);
    end loop;

    return null;
end;
$$ language plpgsql;

select inline_0();
drop function inline_0 ();

--
-- Service contract drop stuff was missing - Roberto Mello 
--

create function inline_0() returns integer as $$
declare
        impl_id integer;
        v_foo   integer;
begin

        -- the notification type impl
        impl_id := acs_sc_impl__get_id (
                      'NotificationType',		-- impl_contract_name
                      'lars_blogger_notif_type' 	-- impl_name
        );

        PERFORM acs_sc_binding__delete (
                    'NotificationType',
                    'lars_blogger_notif_type'
        );

        v_foo := acs_sc_impl_alias__delete (
                    'NotificationType', 		-- impl_contract_name	
                    'lars_blogger_notif_type',  	-- impl_name
                    'GetURL'				-- impl_operation_name
        );

        v_foo := acs_sc_impl_alias__delete (
                    'NotificationType', 	 	-- impl_contract_name	
                    'lars_blogger_notif_type',  	-- impl_name
                    'ProcessReply'      		-- impl_operation_name
        );

	select into v_foo type_id 
	  from notification_types
	 where sc_impl_id = impl_id
	  and short_name = 'lars_blogger_notif';

	perform notification_type__delete (v_foo);

	delete from notification_types_intervals
	 where type_id = v_foo 
	   and interval_id in ( 
		select interval_id
		  from notification_intervals 
		 where name in ('instant','hourly','daily')
	);

	delete from notification_types_del_methods
	 where type_id = v_foo
	   and delivery_method_id in (
		select delivery_method_id
		  from notification_delivery_methods 
		 where short_name in ('email')
	);

	return (0);
end;
$$ language plpgsql;

select inline_0();
drop function inline_0();
    

The next step is to setup our notification creation. A new notification must be added to the notification table for each blog entry added. We do this using the notification::new procedure

        notification::new \
            -type_id [notification::type::get_type_id \
            -short_name lars_blogger_notif] \
            -object_id $blog(package_id) \
            -response_id $blog(entry_id) \
            -notif_subject $blog(title) \
            -notif_text $new_content
    

This code is placed in the Tcl procedure that creates blog entries, right after the entry gets created in the code. The $blog(package_id) is the OpenACS object_id of the Weblogger instance to which the entry has been posted to and the $new_content is the content of the entry. This example uses the package_id for the object_id, which results in setting up notifications for all changes for blogger entries in this package. However, if you instead used the blog_entry_id or something like that, you could set up per-item notifications. The forums packages does this -- you can look at it for an example.

The final step is to setup the notification subscription process. In this example we want to let a user find out when a new entry has been posted to the blog. To do this we put a link on the blog that allows them to subscribe to notifications of new entries. The notifications/requests-new page is very handy in this situation.

Such a link can be created using the notification::display::request_widget proc:

    set notification_chunk [notification::display::request_widget \
        -type lars_blogger_notif \
        -object_id $package_id \
        -pretty_name [lars_blog_name] \
        -url [lars_blog_public_package_url] \
    ]
    

which will return something like

    You may <a href="/notifications/request-new?...">request notification</a> for Weblogger.

which can be readily put on the blog index page. The pretty_name parameter is what appears at the end of the text returned (i.e. "... request notification</a> for pretty_name"), The url parameter should be set to the address we want the user to be redirected to after they have finished the subscription process.

This should be all you need to implement a notification system. For more examples look at the forums package.