Index: openacs-4/packages/rss-support/rss-support.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/rss-support.info,v diff -u -r1.2 -r1.3 --- openacs-4/packages/rss-support/rss-support.info 9 Nov 2001 04:27:00 -0000 1.2 +++ openacs-4/packages/rss-support/rss-support.info 11 Nov 2001 05:36:29 -0000 1.3 @@ -37,9 +37,16 @@ + + + + + + + Index: openacs-4/packages/rss-support/tcl/rss-generation-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/tcl/rss-generation-init.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/rss-support/tcl/rss-generation-init.tcl 11 Nov 2001 05:35:21 -0000 1.1 @@ -0,0 +1 @@ +ad_schedule_proc 1800 rss_gen_service \ No newline at end of file Index: openacs-4/packages/rss-support/tcl/rss-generation-service-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/tcl/rss-generation-service-procs.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/rss-support/tcl/rss-generation-service-procs.tcl 11 Nov 2001 02:01:39 -0000 1.4 +++ openacs-4/packages/rss-support/tcl/rss-generation-service-procs.tcl 11 Nov 2001 05:35:21 -0000 1.5 @@ -2,6 +2,9 @@ ns_log Debug "rss_gen_service: starting" + # Bind any unbound implementations + rss_gen_bind + set n 0 db_foreach timed_out_subscriptions { @@ -53,7 +56,7 @@ } -ad_proc rss_assert_dir path { +ad_proc -private rss_assert_dir path {
     # Steps through path creating each new directory as needed.
     # Accepts full path or relative path, but you probably want
@@ -69,3 +72,35 @@
 	}
     }
 }
+
+ad_proc -private rss_gen_bind {} {
+    
+    # Creates bindings for unbound implementations for RssGenerationSubscriber.
+    
+} { + set contract_id [db_string get_contract_id { + select acs_sc_contract__get_id('RssGenerationSubscriber') + }] + + db_foreach get_unbound_impls { + select impl_id + from acs_sc_impls i + where impl_contract_name = 'RssGenerationSubscriber' + and not exists (select 1 + from acs_sc_bindings b + where b.impl_id = i.impl_id + and b.contract_id = :contract_id) + + } { + ns_log Notice "rss_gen_bind: binding impl $impl_id for contract $contract_id" + # Don't ask me why, but bind variables don't appear to work + # in this nested db operation. + if [catch { + db_exec_plsql bind_impl " + select acs_sc_binding__new($contract_id,$impl_id) + " + } errMsg] { + ns_log Notice "rss_gen_bind: error binding impl $impl_id for contract $contract_id: $errMsg" + } + } +} \ No newline at end of file Index: openacs-4/packages/rss-support/www/doc/bboard-rss-sc-create-sql.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/www/doc/bboard-rss-sc-create-sql.txt,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/rss-support/www/doc/bboard-rss-sc-create-sql.txt 11 Nov 2001 05:35:21 -0000 1.1 @@ -0,0 +1,21 @@ +select acs_sc_impl__new( + 'RssGenerationSubscriber', -- impl_contract_name + 'bboard_forum', -- impl_name + 'bboard' -- impl_owner_name +); + +select acs_sc_impl_alias__new( + 'RssGenerationSubscriber', -- impl_contract_name + 'bboard_forum', -- impl_name + 'datasource', -- impl_operation_name + 'bboard__rss_datasource', -- impl_alias + 'TCL' -- impl_pl +); + +select acs_sc_impl_alias__new( + 'RssGenerationSubscriber', -- impl_contract_name + 'bboard_forum', -- impl_name + 'lastUpdated', -- impl_operation_name + 'bboard__rss_lastUpdated', -- impl_alias + 'TCL' -- impl_pl +); Index: openacs-4/packages/rss-support/www/doc/bboard-rss-sc-procs-tcl.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/www/doc/bboard-rss-sc-procs-tcl.txt,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/rss-support/www/doc/bboard-rss-sc-procs-tcl.txt 11 Nov 2001 05:35:21 -0000 1.1 @@ -0,0 +1,85 @@ +ad_proc -private bboard__rss_datasource { + summary_context_id +} { + This procedure implements the "datasource" operation of the + RssGenerationSubscriber service contract. Its internal details + are entirely up the author provided that it returns a correct + datastructure. + + @author Andrew Grumet +} { + + set this [ad_url] + + db_1row forum_info { + select short_name, + charter, + to_char(now(),'DD Mon YYYY hh12:MI am') as channel_pubdate, + bboard_id + from bboard_forums + where forum_id = :summary_context_id + } + + set bboard_url [rss_first_url_for_package_id $bboard_id] + + set column_array(channel_title) $short_name + set column_array(channel_description) $charter + set column_array(channel_pubDate) $channel_pubdate + + set column_array(version) .91 + + set column_array(channel_link) "${this}${bboard_url}forum?forum_id=$summary_context_id" + set column_array(image) "" + + set last_n_days 0 + + set items [list] + set i 0 + + db_foreach bboard_rss_items " + select message_id, title, + first_names || ' ' || last_name || ' ' as poster, + to_char(last_reply_date,'DD Mon YYYY hh12:MI am') as post_date + from bboard_messages_all b, persons + where forum_id = :summary_context_id + and person_id = sender + and reply_to is null + order by sent_date desc limit 10 + " { + set link "${this}${bboard_url}message?message_id=$message_id&forum_id=$summary_context_id" + lappend items [list link $link title $title description \ + $poster$post_date] + if !$i { + set column_array(channel_lastBuildDate) $post_date + incr i + } + } + set column_array(items) $items + set column_array(channel_language) "" + set column_array(channel_copyright) "" + set column_array(channel_managingEditor) "" + set column_array(channel_webMaster) "" + set column_array(channel_rating) "" + set column_array(channel_skipDays) "" + set column_array(channel_skipHours) "" + + return [array get column_array] +} + +ad_proc -private bboard__rss_lastUpdated { + summary_context_id +} { + Returns the time that the last forum thread was initiated, + in Unix time. Returns 0 otherwise. + + @author Andrew Grumet +} { + db_0or1row get_last_update { + select coalesce (date_part('epoch',max(sent_date)),0) as last_update + from bboard_messages_all + where forum_id = :summary_context_id + and reply_to is null + } + + return $last_update +} \ No newline at end of file Index: openacs-4/packages/rss-support/www/doc/bboard.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/www/doc/bboard.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/rss-support/www/doc/bboard.html 11 Nov 2001 05:35:21 -0000 1.1 @@ -0,0 +1,57 @@ + + +RSS Support: Bboard Sample Implementation + + +

Bboard Sample Implementation

+by Andrew Grumet +
+ +Back to RSS Support + +

+ +The steps: + +

    + +
  1. Create one or more implentations Of the RssGenerationSubscriber +interface. This example +registers an implementation for bboard forums. + +
  2. Define the implementation procs. This example implements the contracted procs. + +
  3. Create a subscription for each context to be summarized. +Until admin pages are available, do this by hand as follows: +
    +select rss_gen_subscr__new (
    +       null,				-- subscr_id
    +       2752,				-- impl_id
    +       2746,				-- summary_context_id (forum_id)
    +       0,				-- timeout
    +       null,				-- lastbuild
    +       'rss_gen_subscr',		-- object_type
    +       now(),				-- creation_date
    +       null,				-- creation_user
    +       null,				-- creation_ip
    +       null				-- context_id
    +);
    +
    + +
  4. The scheduled proc rss_gen_service will create a +binding for the implementation and generate summaries for each +subscription if the conditions for summary generation are met (i.e. if +the subscription timeout interval has elapsed since the last build and +if the time returned by lastUpdated is greater than the time of the +last report built). + +
  5. Summaries can be found at /${RssGenOutputDirectory}/${ImplementationName}/${summary_context_id}/rss.xml + +
+ +
+
+aegrumet@alum.mit.edu + + + Index: openacs-4/packages/rss-support/www/doc/design.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/www/doc/design.html,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/rss-support/www/doc/design.html 11 Nov 2001 05:35:21 -0000 1.1 @@ -0,0 +1,141 @@ + + +RSS Support Design Notes + + +

RSS Support Design Notes

+by Andrew Grumet, +Jerry Asher and +Dave Bauer +
+ +

+ +From the specification, + +

+RDF Site Summary (RSS) is a lightweight multipurpose extensible +metadata description and syndication format. RSS is an XML +application, conforms to the W3C's RDF Specification and is extensible +via XML-namespace and/or RDF based modularization. +
+ +This service package provides low-level support for generating and parsing RSS feeds. + +

1. Feed generation

+ +Feed generation is the process of summarizing local content as RSS +xml. To generate a feed we need to know +
    +
  • the site context whose content is to be summarized, +
  • how to retrieve the various required and optional metadata fields +
  • whether any changes have been made since the last summary was built +
  • how often to rebuild the summary (if changes are present) +
+ +The last item is included with an eye toward performance. In the +event that a particular summary is expensive to produce, we may opt +to rebuild at most every N minutes (or hours, or days). + +

+ +Usage scenarios + +

    + +
  • Publisher wishes to syndicate the Bar Forum in the Foo Bboard package instance. + +
  • Luckily, the bboard package implements the summary service + contract for individual forums. + +
  • Programmer registers the context identifier for the Bar Forum with +the summary service, indicating that the summary should be built no +more than once per hour. + +
  • Summary is available at /some/url/specific/to/bar/forum/summary.xml + +
+ + +

+ +Service contract + +

+ +The feed generation service contract is called RssGenerationSubscriber and consists of two operations. + +

    +
  1. Datasource(summary_context_id) returns a data +structure that contains all required metadata fields plus +configuration information such as the RSS version to be used (0.91 or +1.00 are supported at present). This data structure contains +everything needed to run rss_gen. + +
  2. LastUpdated(summary_context_id) returns a timestamp +that is used to determine if the live summary is out of date. The +timestamp is given as the number of seconds since midnight on January +1, 1970, i.e. Unix time. +
+ +

+ +Under the hood + +

+ +RSS files.All summaries are static files. They are served +from a static directory under the webroot specific by the +RssGenOutputDirectory, which defaults to rss. The full +path to an RSS file is given by +

+/${RssGenOutputDirectory}/${ImplementationName}/${summary_context_id}/rss.xml
+
+ +Note: we assume that ${ImplementationName} and +${summary_context_id} contain OS- and URL-friendly +characters. + +

+ +Subscription. A programmer registers a context with the +summary service through API functions (we can make it possible through +web UI as well if that makes sense). + +

+ +Summary context. A summary context is a content-containing +domain which implements the summary service contract. A summary +context is not identical to a package instance. For example, a single +bboard package instance might contain 3 summary contexts, one for each +of the forums in the instance. + +

+ +Service. A scheduled proc runs through all subscribed +contexts, checking to see if the live summary is stale and also if the +minimum "quiet time" has elapsed. If the conditions for rebuild are +met for a context, the scheduled proc pulls out the context's summary +data via Datasource and uses the information to build a +new summary page. This generic and simple scheme can be used to +dispatch different versions of the summary builder as well as to +support extensibility via modules. Warning: +This design expects the output of Datasource to be +reasonably small, as we will have to parse this list-of-lists to +generate a summary. + +

2. Feed Parsing

+ +(aeg's vague ideas: needs can vary. I can imagine slurping the content into +the db or converting to includable ADPs using XSLT. Service contract +operations are used to generate mappings to RDBMS tables or stylesheets. + + +
+
+aegrumet@alum.mit.edu, +jerry@theashergroup.com, +dave@thedesignexperience.org + + + Index: openacs-4/packages/rss-support/www/doc/index.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/rss-support/www/doc/index.html,v diff -u -r1.4 -r1.5 --- openacs-4/packages/rss-support/www/doc/index.html 11 Nov 2001 02:01:39 -0000 1.4 +++ openacs-4/packages/rss-support/www/doc/index.html 11 Nov 2001 05:35:21 -0000 1.5 @@ -9,128 +9,22 @@ Dave Bauer
-

- -From the specification, - -

-RDF Site Summary (RSS) is a lightweight multipurpose extensible -metadata description and syndication format. RSS is an XML -application, conforms to the W3C's RDF Specification and is extensible -via XML-namespace and/or RDF based modularization. -
- -This service package provides low-level support for generating and parsing RSS feeds. - -

1. Feed generation

- -Feed generation is the process of summarizing local content as RSS -xml. To generate a feed we need to know
    -
  • the site context whose content is to be summarized, -
  • how to retrieve the various required and optional metadata fields -
  • whether any changes have been made since the last summary was built -
  • how often to rebuild the summary (if changes are present) -
- -The last item is included with an eye toward performance. In the -event that a particular summary is expensive to produce, we may opt -to rebuild at most every N minutes (or hours, or days). - +
  • Design Notes +
  • Bboard Sample Implementation

    - -Usage scenarios - -

      - -
    • Publisher wishes to syndicate the Bar Forum in the Foo Bboard package instance. - -
    • Luckily, the bboard package implements the summary service - contract for individual forums. - -
    • Programmer registers the context identifier for the Bar Forum with -the summary service, indicating that the summary should be built no -more than once per hour. - -
    • Summary is available at /some/url/specific/to/bar/forum/summary.xml - +
    • To-do's +
        +
      1. Admin screens for subscription management +
      2. Exception handling +
      3. Testing +
    -

    -Service contract -

    -The feed generation service contract is called RssGenerationSubscriber and consists of two operations. - -

      -
    1. Datasource(summary_context_id) returns a data -structure that contains all required metadata fields plus -configuration information such as the RSS version to be used (0.91 or -1.00 are supported at present). This data structure contains -everything needed to run rss_gen. - -
    2. LastUpdated(summary_context_id) returns a timestamp -that is used to determine if the live summary is out of date. The -timestamp is given as the number of seconds since midnight on January -1, 1970, i.e. Unix time. -
    - -

    - -Under the hood - -

    - -RSS files.All summaries are static files. They are served -from a static directory under the webroot specific by the -RssGenOutputDirectory, which defaults to rss. The full -path to an RSS file is given by -

    -/${RssGenOutputDirectory}/${ImplementationName}/${summary_context_id}/rss.xml
    -
    - -Note: we assume that ${ImplementationName} and -${summary_context_id} contain OS- and URL-friendly -characters. - -

    - -Subscription. A programmer registers a context with the -summary service through API functions (we can make it possible through -web UI as well if that makes sense). - -

    - -Summary context. A summary context is a content-containing -domain which implements the summary service contract. A summary -context is not identical to a package instance. For example, a single -bboard package instance might contain 3 summary contexts, one for each -of the forums in the instance. - -

    - -Service. A scheduled proc runs through all subscribed -contexts, checking to see if the live summary is stale and also if the -minimum "quiet time" has elapsed. If the conditions for rebuild are -met for a context, the scheduled proc pulls out the context's summary -data via Datasource and uses the information to build a -new summary page. This generic and simple scheme can be used to -dispatch different versions of the summary builder as well as to -support extensibility via modules. Warning: -This design expects the output of Datasource to be -reasonably small, as we will have to parse this list-of-lists to -generate a summary. - -

    2. Feed Parsing

    - -(aeg's vague ideas: needs can vary. I can imagine slurping the content into -the db or converting to includable ADPs using XSLT. Service contract -operations are used to generate mappings to RDBMS tables or stylesheets. - -
    aegrumet@alum.mit.edu,