Index: openacs-4/packages/dynamic-types/tcl/00-event-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/dynamic-types/tcl/00-event-init.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/dynamic-types/tcl/00-event-init.tcl 4 Sep 2005 12:13:28 -0000 1.5
@@ -0,0 +1,11 @@
+ad_library {
+
+ Initialise the event dispatcher nsv.
+
+ @author Lee Denison (lee@thaum.net)
+ @creation-date 2004-03-17
+ @cvs-id $Id: 00-event-init.tcl,v 1.5 2005/09/04 12:13:28 maltes Exp $
+
+}
+
+nsv_set util_events lock [ns_mutex create]
Index: openacs-4/packages/dynamic-types/tcl/dynamic-type-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/dynamic-types/tcl/dynamic-type-init.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/dynamic-types/tcl/dynamic-type-init.tcl 4 Sep 2005 12:13:28 -0000 1.5
@@ -0,0 +1,15 @@
+ad_library {
+ Register attribute callbacks.
+
+ @author Lee Denison (lee@xarg.net)
+ @creation-date 2004/11/11
+ @cvs-id $Id: dynamic-type-init.tcl,v 1.5 2005/09/04 12:13:28 maltes Exp $
+}
+
+util::event::register -event dtype \
+ -match { action (updated|deleted) } \
+ { dtype::flush_cache -type $type -event event }
+
+util::event::register -event dtype.attribute \
+ -match { action (created|updated|deleted) } \
+ { dtype::flush_cache -type $type -event event }
Index: openacs-4/packages/dynamic-types/tcl/dynamic-type-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/dynamic-types/tcl/dynamic-type-procs.tcl,v
diff -u -N -r1.7 -r1.8
--- openacs-4/packages/dynamic-types/tcl/dynamic-type-procs.tcl 7 Jul 2005 14:00:08 -0000 1.7
+++ openacs-4/packages/dynamic-types/tcl/dynamic-type-procs.tcl 4 Sep 2005 12:13:28 -0000 1.8
@@ -129,9 +129,14 @@
db_exec_plsql drop_type {}
+ set event(object_type) $name
+ set event(action) deleted
+ util::event::fire -event dtype event
+
if {!$no_flush_p} {
- dtype::flush_cache -type $name
+ dtype::flush_cache -type $name -event event
}
+
}
ad_proc -public dtype::create_attribute {
@@ -164,10 +169,16 @@
}
db_exec_plsql create_attr {}
+
+ set event(object_type) $object_type
+ set event(attribute) $name
+ set event(action) created
+ util::event::fire -event dtype.attribute event
if {!$no_flush_p} {
- dtype::flush_cache -type $name
+ dtype::flush_cache -type $name -event event
}
+
}
ad_proc -public dtype::get_attributes {
@@ -244,10 +255,15 @@
ad_proc -private dtype::flush_cache {
{-type:required}
+ {-event:required}
} {
Flushes the util_memoize cache of dtype calls for a given object type.
+
+ event is assumed to be a name of an array that contains object_type and action
} {
- util_memoize_flush_regexp "dtype::get_attributes_list -no_cache -name \"$type\".*"
+ upvar $event dtype_event
+
+ util_memoize_flush_regexp "dtype::get_attributes_list -no_cache -name \"$dtype_event(object_type)\".*"
}
ad_proc -public dtype::edit_attribute {
@@ -262,8 +278,13 @@
} {
db_dml update_attribute {}
+ set event(object_type) $object_type
+ set event(attribute) $name
+ set event(action) updated
+ util::event::fire -event dtype.attribute event
+
if {!$no_flush_p} {
- dtype::flush_cache -type $name
+ dtype::flush_cache -type $name -event event
}
}
@@ -289,8 +310,13 @@
db_exec_plsql drop_attr {}
+ set event(object_type) $object_type
+ set event(attribute) $name
+ set event(action) deleted
+ util::event::fire -event dtype.attribute event
+
if {!$no_flush_p} {
- dtype::flush_cache -type $name
+ dtype::flush_cache -type $name -event event
}
}
Index: openacs-4/packages/dynamic-types/tcl/event-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/dynamic-types/tcl/event-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/dynamic-types/tcl/event-procs.tcl 4 Sep 2005 12:13:28 -0000 1.5
@@ -0,0 +1,151 @@
+ad_library {
+ A library which dispatches tcl callback events.
+
+ Events are assigned heirarchical symbolic names, eg:
+
+ major-type
+ major-type.minor-type
+ major-type.minor-type.leaf-type
+
+ Event handlers register which types they respond to, eg:
+
+ major-type
+ - respond only to exact match 'major-type' events
+
+ major-type.
+ - respond to all 'major-type' and subtype events
+
+ major-type.minor-type.
+ - respond to only to 'major-type.minor-type' and subtype events
+
+ When an event is triggered an array called 'event' is made available to
+ the handler containing information about the event. At registration time
+ a handler can specify criteria which must be matched in the event array
+ for this handler to be triggered.
+
+ Functions that fire events should document what information they include
+ in the event array. They should normally include an action which is a
+ verb in the past tense 'created' for events that have just happened or a
+ verb in the present tense 'creating' for events that are about to happen.
+
+ Most events won't need this level of flexibility but I did for the stuff
+ I was doing when I wrote this.
+
+ @author Lee Denison (lee@xarg.net)
+ @creation-date 2004/11/11
+ @cvs-id $Id: event-procs.tcl,v 1.5 2005/09/04 12:13:28 maltes Exp $
+}
+
+namespace eval util {}
+namespace eval util::event {}
+
+ad_proc -public util::event::register {
+ {-event:required}
+ {-match {}}
+ script
+} {
+ Registers script
to be run on event
if the
+ criteria in match
are satisfied.
+} {
+ set handler [list $match $script]
+
+ ns_mutex lock [nsv_get util_events lock]
+ nsv_lappend util_events $event $handler
+ ns_mutex unlock [nsv_get util_events lock]
+}
+
+ad_proc -public util::event::unregister {
+ {-event:required}
+ {-match {}}
+ script
+} {
+ Unregisters script
from event event
where the
+ criteria in match
are required.
+} {
+ ns_mutex lock [nsv_get util_events lock]
+ if {[nsv_exists util_events $event]} {
+ set handlers [nsv_get util_events $event]
+
+ set result [list]
+ foreach handler $handlers {
+ set cand_match [lindex $handler 0]
+ set cand_script [lindex $handler 1]
+
+ if {![string match $script $cand_scripts] ||
+ ![util::event::compare_matches $match $cand_match]} {
+ lappend result $handler
+ }
+ }
+
+ nsv_set util_events $event $result
+ }
+ ns_mutex unlock [nsv_get util_events lock]
+}
+
+ad_proc -private util::event::compare_matches {
+ match1
+ match2
+} {
+ Compares two match lists for equality.
+} {
+ foreach crit1 $match1 {
+ foreach crit2 $match2 {
+ if {![string equal [lindex $crit1 0] [lindex $crit2 0]] ||
+ ![string equal [lindex $crit1 1] [lindex $crit2 1]]} {
+ return 0
+ }
+ }
+ }
+
+ return 1
+}
+
+ad_proc -public util::event::fire {
+ {-event:required}
+ data
+} {
+ Fires any scripts registered to event for which the match criteria are
+ satisfied.
+
+ Each event script is executed with access to an event array containing the
+ event data. Consult the documentation of the function that fires the
+ fires the event to see what data is available in the event.
+} {
+ set type $event
+ set type_elms [split $event "."]
+ set type_bins [list $event]
+ unset event
+
+ upvar $data event
+
+ for {set i 0} {$i < [llength $type_elms]} {incr i} {
+ lappend type_bins "[join [lrange $type_elms 0 $i] "."]."
+ }
+
+ set results [list]
+
+ foreach type_bin $type_bins {
+ if {[nsv_exists util_events $type_bin]} {
+ set handlers [nsv_get util_events $type_bin]
+
+ foreach handler $handlers {
+ array set match [lindex $handler 0]
+ set script [lindex $handler 1]
+ set matches_p 1
+
+ foreach key [array names match] {
+ set matches_p \
+ [expr {$matches_p ||
+ [regexp -- $match($key) $event($key)]}]
+
+ }
+
+ if {$matches_p} {
+ lappend results [eval $script]
+ }
+ }
+ }
+ }
+
+ return $results
+}