Index: openacs-4/packages/xotcl-core/xotcl-core.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/xotcl-core.info,v
diff -u -N -r1.22 -r1.22.2.1
--- openacs-4/packages/xotcl-core/xotcl-core.info 29 Dec 2006 11:04:16 -0000 1.22
+++ openacs-4/packages/xotcl-core/xotcl-core.info 1 Aug 2007 21:39:31 -0000 1.22.2.1
@@ -8,10 +8,10 @@
t
xotcl
-
+
Gustaf Neumann
XOTcl library functionality (e.g. thread handling, online documentation, Generic Form and List Classes)
- 2006-12-29
+ 2007-08-01
This component contains some core functionality for OACS
applications using XOTcl. It includes
XOTcl thread handling for OACS (supporting persistent and
@@ -30,11 +30,16 @@
0.41: supporting storage_type file, on_submit method and html for forms;
0.43: context and connection context;
0.44: use connection_context, sch regression test works;
-0.45: xo:db require operations;
+0.45: xo:db require operations;
+0.48: policies
+0.49: stored procedures object proxies (postgres and Oracle)
+0.51: require package
+0.52: distinguish between ImageField and ImageAnchorField, start using slots, multivalued form entries, bulk-actions, improved localization, improved sql layer (:.xo::db::sql)
+
BSD-Style
0
-
+
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml,v
diff -u -N -r1.4.2.1 -r1.4.2.2
--- openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml 23 Apr 2007 05:55:08 -0000 1.4.2.1
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.de_DE.ISO-8859-1.xml 1 Aug 2007 21:39:31 -0000 1.4.2.2
@@ -1,5 +1,5 @@
-
+
Neu: %type%
Neue Seite vom Type %type% erzeugen
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml,v
diff -u -N -r1.4.2.1 -r1.4.2.2
--- openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml 23 Apr 2007 05:55:08 -0000 1.4.2.1
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.en_US.ISO-8859-1.xml 1 Aug 2007 21:39:31 -0000 1.4.2.2
@@ -1,5 +1,5 @@
-
+
Add %type%
Add new item of type %type%
@@ -8,6 +8,9 @@
Edit %type%
has entered the room
Live Revision
+ <blockquote>
+You don't have sufficient permissions for performing method %method% on object %object%.
+</blockquote>
Revisions of Entry
Revisions
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.es_ES.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.es_ES.ISO-8859-1.xml,v
diff -u -N -r1.1.4.2 -r1.1.4.3
--- openacs-4/packages/xotcl-core/catalog/xotcl-core.es_ES.ISO-8859-1.xml 22 Mar 2007 10:14:02 -0000 1.1.4.2
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.es_ES.ISO-8859-1.xml 1 Aug 2007 21:39:31 -0000 1.1.4.3
@@ -1,13 +1,13 @@
-
+
A�adir %type%
- A�adir un nuevo item del tipo %type%
- Crear nuevo %type%
- Editar item
+ A�adir un nuevo �tem del tipo %type%
+ Crear Nuevo %type%
+ Editar �tem
Editar %type%
ha entrado en la sala
- Revisi�n Actual
- Revisiones para la entrada
+ Revisi�n Viva
+ Revisiones de la Entrada
Revisiones
Index: openacs-4/packages/xotcl-core/catalog/xotcl-core.pt_BR.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/catalog/xotcl-core.pt_BR.ISO-8859-1.xml,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/catalog/xotcl-core.pt_BR.ISO-8859-1.xml 1 Aug 2007 21:39:31 -0000 1.1.4.2
@@ -0,0 +1,11 @@
+
+
+
+ Adicionar %type%
+ Adicionar novo item tipo %type%
+ Editar Item
+ Entrou na sala
+ Revis�o Ativa
+ Revis�es da Entrada
+ Revis�es
+
Index: openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl,v
diff -u -N -r1.8 -r1.8.2.1
--- openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl 17 Nov 2006 21:29:17 -0000 1.8
+++ openacs-4/packages/xotcl-core/tcl/01-debug-procs.tcl 1 Aug 2007 21:39:31 -0000 1.8.2.1
@@ -1,10 +1,14 @@
## tell serializer to export methods, although these are methods of
# ::xotcl::Object
+package require xotcl::serializer
+
::Serializer exportMethods {
::xotcl::Object instproc log
+ ::xotcl::Object instproc msg
+ ::xotcl::Object instproc __timediff
::xotcl::Object instproc debug
- ::xotcl::Object instproc contains
+ ::xotcl::Object instproc qn
::xotcl::Object instproc serialize
::xotcl::Object instforward db_1row
::xotcl::Object instproc destroy_on_cleanup
@@ -23,6 +27,44 @@
my requireNamespace
namespace eval [self] $cmds
}
+ namespace eval ::xo {
+ Class create ::xo::Attribute \
+ -parameter {
+ {name "[namespace tail [::xotcl::self]]"}
+ {domain "[lindex [regexp -inline {^(.*)::slot::[^:]+$} [::xotcl::self]] 1]"}
+ {multivalued false}
+ {required false}
+ default
+ type
+ spec
+ pretty_name
+ {pretty_plural ""}
+ {datatype "text"}
+ {sqltype "text"}
+ {min_n_values 1}
+ {max_n_values 1}
+ help_text
+ validator
+ }
+
+ }
+} else {
+ namespace eval ::xo {
+ Class create ::xo::Attribute \
+ -superclass ::xotcl::Attribute \
+ -parameter {
+ spec
+ {required false}
+ pretty_name
+ {pretty_plural ""}
+ {datatype "text"}
+ {sqltype "text"}
+ {min_n_values 1}
+ {max_n_values 1}
+ help_text
+ validator
+ }
+ }
}
::xotcl::Object instforward db_1row -objscope
@@ -31,25 +73,28 @@
::Serializer deepSerialize [self]
}
+namespace eval ::xo {
+ ::xotcl::Class create ::xo::InstanceManager \
+ -instproc alloc args {
+ set r [next]
+ set key blueprint($r)
+ if {![ns_conn isconnected]} {
+ [self class] set $key 1
+ } elseif {![[self class] exists $key]} {
+ [self class] set connectionobject($r) 1
+ }
+ return $r
+ } \
+ -instproc destroy args {
+ next
+ ns_log notice "--unset -nocomplain [self class]::blueprint([self])"
+ [self class] unset -nocomplain blueprint([self])
+ [self class] unset -nocomplain connectionobject([self])
+ }
-# Currently, xotcl's serializer does not export ::xotcl::* commands,
-# except methods for ::xotcl::Object and ::xotcl::Core, so we use the
-# mixin instead of te direct defintion... should be changed in the future
-# namespace eval ::xo {
-# Class create ::xo::NonPosArgs \
-# -instproc integer args {
-# if {[llength $args] < 2} return
-# foreach {name value} $args break
-# if {![string is integer $value]} {
-# error "value '$value' of $name not an integer"
-# }
-# } \
-# -instproc optional {name args} {
-# ;
-# }
-# }
-# ::xotcl::nonposArgs proc integer
-# ::xotcl::nonposArgs proc optional
+ # deactivate for now
+ #::xotcl::Object instmixin add ::xo::InstanceManager
+}
::xotcl::nonposArgs proc integer args {
if {[llength $args] < 2} return
@@ -60,7 +105,7 @@
;
}
-::xotcl::Object instproc log msg {
+::xotcl::Object instproc __timediff {} {
set now [ns_time get]
if {[ns_conn isconnected]} {
set start_time [ns_conn start]
@@ -77,14 +122,26 @@
} else {
set diff ""
}
- ns_log notice "$msg, [self] [self callingclass]->[self callingproc] (${ms}ms$diff)"
set ::__last_timestamp $now
+ return "${ms}ms$diff"
}
+::xotcl::Object instproc log msg {
+ ns_log notice "$msg, [self] [self callingclass]->[self callingproc] ([my __timediff])"
+}
+
::xotcl::Object instproc debug msg {
ns_log debug "[self] [self callingclass]->[self callingproc]: $msg"
}
-
+::xotcl::Object instproc msg msg {
+ if {[ns_conn isconnected]} {
+ util_user_message -message "$msg ([self] [self callingclass]->[self callingproc])"
+ }
+}
+::xotcl::Object instproc qn query_name {
+ set qn "dbqd.[my uplevel self class]-[my uplevel self proc].$query_name"
+ return $qn
+}
namespace eval ::xo {
Class Timestamp
Timestamp instproc init {} {my set time [clock clicks -milliseconds]}
@@ -125,26 +182,9 @@
}
}
- #
- # a simple calback for cleanup of per connection objects
- # ns_atclose is a little to early for us...
- #
- ::xotcl::Object instproc destroy_on_cleanup {} {
- set ::xotcl_cleanup([self]) 1
- #my log "--A cleanup for [lsort [array names ::xotcl_cleanup]]"
- ::trace add variable ::xotcl_cleanup([self]) unset ::xo::cleanup_callback
- }
- proc ::xo::cleanup_callback {var object op} {
- if {![::xotcl::Object isobject $object]} {
- #ns_log notice "--D $object already destroyed, nothing to do"
- $object destroy
- } else {
- #ns_log notice "--D $object destroy"
- $object destroy
- }
- }
}
+
# ::xotcl::Class instproc import {class pattern} {
# namespace eval [self] [list \
# namespace import [list import [$class self]]::$pattern;
@@ -168,3 +208,113 @@
# ns_log notice "--T [ns_ictl get]"
#}
+namespace eval ::xo {
+ #
+ # In earlier versions of xotcl-core, we used variable traces
+ # to trigger deletion of objects. This had two kind of problems:
+ # 1) there was no way to control the order of the deletions
+ # 2) the global variables used for managing db handles might
+ # be deleted already
+ # 3) the traces are executed at a time when the connection
+ # is already closed
+ # Aolserver 4.5 supports a trace for freeconn. We can register
+ # a callback to be executed before the connection is freed,
+ # therefore, we have still information from ns_conn available.
+ # For aolserver 4.5 we use oncleanup, which is at least before
+ # the cleanup of variables.
+ #
+ # In contrary, in 4.0.10, on cleanup is called after the global
+ # variables of a connection thread are deleted. Therefore
+ # the triggered calls should not use database handles,
+ # since these are as well managed via global variables,
+ # the will be deleted as well at this time,.
+ #
+ # To come up with an approach working for 4.5 and 4.0.10, we
+ # distinguish between a at_cleanup and at_close, so connection
+ # related info can still be obtained.
+ #
+ if {[catch {set registered [ns_ictl gettraces freeconn]}]} {
+ ns_log notice "*** you should really upgrade to Aolserver 4.5"
+ # "ns_ictl oncleanup" is called after variables are deleted
+ if {[ns_ictl epoch] == 0} {
+ ns_ictl oncleanup ::xo::at_cleanup
+ ns_ictl oninit [list ns_atclose ::xo::at_close]
+ }
+
+# proc trace_cleanup {args} {
+# set name [lindex $args 1]
+# #ns_log notice "*** cleanup <$args> '$name'"
+# if {[::xotcl::Object isobject $name]} {
+# ns_log notice "*** cleanup $name destroy"
+# $name destroy
+# }
+# }
+ } else {
+
+ # register only once
+ if {[lsearch $registered ::xo::cleanup] == -1} {
+ ns_ictl trace freeconn ::xo::freeconn
+ }
+
+ proc ::xo::freeconn {} {
+ catch {::xo::at_close}
+ catch {::xo::at_cleanup}
+ }
+ }
+
+ #proc ::xo::at_create {} {
+ # ns_log notice "--at_create *********"
+ # foreach i [::xo::InstanceManager array names blueprint] {
+ # if {![::xotcl::Object isobject $i]} {
+ # ::xo::InstanceManager unset blueprint($i)
+ # ns_log notice "--at_create no such object: $i"
+ # }
+ # }
+ #}
+
+ ::xotcl::Object instproc destroy_on_cleanup {} {
+ #my log "--cleanup adding ::xo::cleanup([self]) [list [self] destroy]"
+ set ::xo::cleanup([self]) [list [self] destroy]
+ }
+
+ proc at_close {args} {
+ }
+
+ proc at_cleanup {args} {
+ #ns_log notice "*** start of cleanup <$args> ([array get ::xo::cleanup])"
+ set at_end ""
+ foreach {name cmd} [array get ::xo::cleanup] {
+ #::trace remove variable ::xotcl_cleanup($name) unset ::xo::cleanup
+ if {![::xotcl::Object isobject $name]} {
+ #ns_log notice "--D $name already destroyed, nothing to do"
+ continue
+ }
+ if {$name eq "::xo::cc"} {
+ append at_end $cmd\n
+ continue
+ }
+ #ns_log notice "*** cleanup $cmd"
+ if {[catch {eval $cmd} errorMsg]} {
+ set obj [lindex $cmd 0]
+ ns_log notice "Error during ::xo::cleanup: $errorMsg $::errorInfo"
+ catch {
+ ns_log notice "... analyze: cmd = $cmd"
+ ns_log notice "... analyze: $obj is_object? [::xotcl::Object isobject $obj]"
+ ns_log notice "... analyze: class [$obj info class]"
+ ns_log notice "... analyze: precedence [$obj info precedence]"
+ ns_log notice "... analyze: methods [lsort [$obj info methods]]"
+ }
+ }
+ }
+ #ns_log notice "*** at_end $at_end"
+ if {[catch {eval $at_end} errorMsg]} {
+ ns_log notice "Error during ::xo::cleanup: $errorMsg $::errorInfo"
+ }
+ array unset ::xo::cleanup
+ #ns_log notice "*** end of cleanup"
+ }
+}
+
+#ns_log notice "*** FREECONN? [ns_ictl gettraces freeconn]"
+#ns_ictl trace freeconn {ns_log notice "*** FREECONN isconnected=[ns_conn isconnected]"}
+#ns_ictl oncleanup {ns_log notice "*** ONCLEANUP isconnected=[ns_conn isconnected]"}
Index: openacs-4/packages/xotcl-core/tcl/03-doc-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/03-doc-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/03-doc-procs.tcl 1 Aug 2007 21:39:31 -0000 1.1.2.2
@@ -0,0 +1,335 @@
+ad_library {
+ XOTcl API for api browser, defines the methods
+ ad_proc (for object specific methods),
+ ad_instproc (for tradional methods) and
+ ad_odc (for documenting classes). Syntax for the methods
+ ad_proc and ad_instproc is like oacs ad_proc, ad_doc
+ receives one argument, similar to ad_library.
+
+ @author Gustaf Neumann
+ @creation-date 2005-05-13
+ @cvs-id $Id: 03-doc-procs.tcl,v 1.1.2.2 2007/08/01 21:39:31 gustafn Exp $
+}
+
+# Per default, the content of the ::xotcl:: namespace is not serialized;
+# so we add the specified methods explizitely to the export list
+::Serializer exportMethods {
+ ::xotcl::Object instproc ad_proc
+ ::xotcl::Object instproc ad_forward
+ ::xotcl::Class instproc ad_instproc
+ ::xotcl::Class instproc ad_instforward
+ ::xotcl::Object instproc ad_doc
+ ::xotcl::Object instproc __api_make_doc
+ ::xotcl::Object instproc __api_make_forward_doc
+}
+::Serializer exportObjects {
+ ::xotcl::api
+}
+
+::xotcl::Object create ::xotcl::api \
+ -proc isclass {scope obj} {
+ expr {$scope eq "" ?
+ [::xotcl::Object isclass $obj] :
+ [$scope do ::xotcl::Object isclass $obj]}
+ } -proc isobject {scope obj} {
+ expr {$scope eq "" ?
+ [::xotcl::Object isobject $obj] :
+ [$scope do ::xotcl::Object isobject $obj]}
+ } -proc scope {} {
+ if {[info exists ::xotcl::currentThread]} {
+ # we are in an xotcl thread; the body won't be accessible directly
+ return $::xotcl::currentThread
+ }
+ return ""
+
+ } -proc scope_from_object_reference {scope_var object_var} {
+ upvar $scope_var scope $object_var object
+ set scope ""
+ regexp {^(.+) do (.+)$} $object match scope object
+
+ } -proc scope_from_proc_index {proc_index} {
+ set scope ""
+ regexp {^(.+) .+ (inst)?proc (.+)$} $proc_index match scope
+ return $scope
+
+ } -proc inscope {scope args} {
+ expr {$scope eq "" ? [eval $args] : [eval $scope do $args]}
+
+ } -proc script_name {scope} {
+ #set kind [expr {[my istype ::xotcl::Class] ? "Class" : "Object"}]
+ #return "$scope$kind [self]"
+ set script [info script]
+ if {$script eq "" && [info exists ::xotcl::currentScript]} {
+ set script $::xotcl::currentScript
+ }
+ set root_dir [nsv_get acs_properties root_directory]
+ set root_length [string length $root_dir]
+ if { $root_dir eq [string range $script 0 [expr {$root_length - 1}]]} {
+ set script [string range $script [expr {$root_length + 1}] end]
+ }
+ return $script
+
+ } -proc object_link {{-noimg:boolean off} scope obj} {
+ set link ""
+ if {$noimg} {
+ return "$link$obj "
+ } else {
+ return "$obj$link "
+ }
+
+ } -proc object_url {{-show_source 0} {-show_methods 1} scope obj} {
+ set object [expr {$scope eq "" ? $obj : "$scope do $obj"}]
+ return [export_vars -base /xotcl/show-object {object show_source show_methods}]
+ } -proc object_index {scope obj} {
+ set kind [expr {[my isclass $scope $obj] ? "Class" : "Object"}]
+ return "$scope$kind $obj"
+
+ } -proc proc_index {scope obj instproc proc_name} {
+ if {$scope eq ""} {
+ return "$obj $instproc $proc_name"
+ } else {
+ return "$scope $obj $instproc $proc_name"
+ }
+
+ } -proc source_to_html {{-width 100} string} {
+ set lines [list]
+ foreach l [split $string \n] {
+ while {[string length $l] > $width} {
+ set pos [string last " \{" $l $width]
+ if {$pos>10} {
+ lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
+ set l " [string range $l $pos end]"
+ } else {
+ # search for a match right of the target
+ set pos [string first " \{" $l $width]
+ if {$pos>10} {
+ lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
+ set l " [string range $l $pos end]"
+ } else {
+ # last resort try to split around spaces
+ set pos [string last " " $l $width]
+ if {$pos>10} {
+ lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
+ set l " [string range $l $pos end]"
+ } else {
+ break
+ }
+ }
+ }
+ }
+ lappend lines $l
+ }
+ set string [join $lines \n]
+ set html [ad_quotehtml $string]
+ regsub -all {(\n[\t ]*)(\#[^\n]*)} $html \\1\\2 html
+ return "$html "
+ }
+
+
+
+
+::xotcl::Object instproc __api_make_doc {inst proc_name} {
+ upvar doc doc private private public public deprecated deprecated
+ if {$doc eq ""} {
+ set doc_elements(main) ""
+ } else {
+ ad_parse_documentation_string $doc doc_elements
+ }
+ set defaults [list]
+ foreach a [my info ${inst}args $proc_name] {
+ if {[my info ${inst}default $proc_name $a d]} {lappend defaults $a $d}
+ }
+ set public [expr {$private ? false : true}]
+ set doc_elements(public_p) $public
+ set doc_elements(private_p) $private
+ set doc_elements(deprecated_p) $deprecated
+ set doc_elements(varargs_p) [expr {[lsearch args [my info ${inst}args $proc_name]]>-1}]
+ set doc_elements(flags) [list]
+ set doc_elements(switches) [list]
+ foreach f [my info ${inst}nonposargs $proc_name] {
+ set pair [split [lindex $f 0 0] :]
+ set sw [string range [lindex $pair 0] 1 end]
+ lappend doc_elements(switches) $sw
+ lappend doc_elements(flags) $sw [lindex $pair 1]
+ #my log "default_value $proc_name: $sw -> '[lindex $f 1]' <$pair/$f>"
+ if {[lindex $pair 1] eq "switch" && [lindex $f 1] eq ""} {
+ set default "false"
+ } else {
+ set default [lindex $f 1]
+ }
+ #my log "default_value $proc_name: $sw -> 'default' <$pair/$f>"
+ lappend defaults $sw $default
+ }
+ set doc_elements(default_values) $defaults
+ set doc_elements(positionals) [my info ${inst}args $proc_name]
+ # argument documentation finished
+ set scope [::xotcl::api scope]
+ set doc_elements(script) [::xotcl::api script_name $scope]
+ set proc_index [::xotcl::api proc_index $scope [self] ${inst}proc $proc_name]
+ if {![nsv_exists api_proc_doc $proc_index]} {
+ nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
+ }
+ #my log "doc_elements=[array get doc_elements]"
+ #my log "SETTING api_proc_doc '$proc_index'"
+ nsv_set api_proc_doc $proc_index [array get doc_elements]
+}
+
+::xotcl::Object instproc __api_make_forward_doc {inst method_name} {
+ upvar doc doc private private public public deprecated deprecated
+ if {$doc eq ""} {
+ set doc_elements(main) ""
+ } else {
+ ad_parse_documentation_string $doc doc_elements
+ #my log "doc_elements=[array get doc_elements]"
+ }
+ set defaults [list]
+ set public [expr {$private ? false : true}]
+ set doc_elements(public_p) $public
+ set doc_elements(private_p) $private
+ set doc_elements(deprecated_p) $deprecated
+ set doc_elements(varargs_p) false
+ set doc_elements(flags) [list]
+ set doc_elements(switches) [list]
+ set doc_elements(default_values) [list]
+ set doc_elements(positionals) [list]
+ # argument documentation finished
+ set scope [::xotcl::api scope]
+ set doc_elements(script) [::xotcl::api script_name $scope]
+ set proc_index [::xotcl::api proc_index $scope [self] ${inst}forward $method_name]
+ if {![nsv_exists api_proc_doc $proc_index]} {
+ nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
+ }
+ #my log "doc_elements=[array get doc_elements]"
+ #my log "SETTING api_proc_doc '$proc_index'"
+ nsv_set api_proc_doc $proc_index [array get doc_elements]
+}
+
+::xotcl::Object instproc ad_proc {
+ {-private:switch false}
+ {-deprecated:switch false}
+ {-warn:switch false}
+ {-debug:switch false}
+ proc_name arguments doc body} {
+ uplevel [list [self] proc $proc_name $arguments $body]
+ my __api_make_doc "" $proc_name
+ }
+
+::xotcl::Object instproc ad_forward {
+ {-private:switch false}
+ {-deprecated:switch false}
+ {-warn:switch false}
+ {-debug:switch false}
+ method_name doc args} {
+ uplevel [self] forward $method_name $args
+ my __api_make_forward_doc "" $method_name
+ }
+
+::xotcl::Class instproc ad_instproc {
+ {-private:switch false}
+ {-deprecated:switch false}
+ {-warn:switch false}
+ {-debug:switch false}
+ proc_name arguments doc body} {
+ uplevel [list [self] instproc $proc_name $arguments $body]
+ my __api_make_doc inst $proc_name
+ }
+
+::xotcl::Object instproc ad_instforward {
+ {-private:switch false}
+ {-deprecated:switch false}
+ {-warn:switch false}
+ {-debug:switch false}
+ method_name doc args} {
+ uplevel [self] instforward $method_name $args
+ my __api_make_forward_doc inst $method_name
+ }
+
+
+
+::xotcl::Object instproc ad_doc {doc_string} {
+ ad_parse_documentation_string $doc_string doc_elements
+ set scope [::xotcl::api scope]
+ set doc_elements(script) [::xotcl::api script_name $scope]
+ set proc_index [::xotcl::api object_index $scope [self]]
+
+ #if {![nsv_exists api_proc_doc $proc_index]} {
+ # nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
+ #}
+ set doc_elements(public_p) true
+ set doc_elements(private_p) false
+ set doc_elements(varargs_p) false
+ set doc_elements(deprecated_p) false
+ set doc_elements(default_values) ""
+ set doc_elements(switches) ""
+ set doc_elements(positionals) ""
+ set doc_elements(flags) ""
+ nsv_set api_proc_doc $proc_index [array get doc_elements]
+ nsv_set api_library_doc \
+ $proc_index \
+ [array get doc_elements]
+
+ set file_index $doc_elements(script)
+
+ if {[nsv_exists api_library_doc $file_index]} {
+ array set elements [nsv_get api_library_doc $file_index]
+ }
+ set oldDoc [expr {[info exists elements(main)] ? \
+ [lindex $elements(main) 0] : ""}]
+ set prefix "This file defines the following Objects and Classes"
+ set entry [::xotcl::api object_link $scope [self]]
+ if {![string match *$prefix* $oldDoc]} {
+ append oldDoc "$prefix: $entry"
+ } else {
+ append oldDoc ", $entry"
+ }
+ set elements(main) [list $oldDoc]
+ #my log "elements = [array get elements]"
+ nsv_set api_library_doc $file_index [array get elements]
+}
+
+
+Class ::Test -ad_doc {
+ Test Class for the documentation of
+ Classes
,
+ Objects
,
+ instprocs
, and
+ procs
.
+ @author Gustaf Neumann
+ @cvs-id $Id: 03-doc-procs.tcl,v 1.1.2.2 2007/08/01 21:39:31 gustafn Exp $
+}
+::Test ad_proc my-class-specific-proc {x y} {
+ This is a proc of Class Test merely for testing purposes...
+ @param x First Operand
+ @param y Second Operand
+} {
+ ns_log notice "hello world $x $y"
+}
+
+::Test ad_instproc my-method {-id:required} {
+ This is an instproc of Class Test merely for testing purposes...
+ @param id Some Id
+} {
+ ns_log notice "hello world $id"
+}
+::Test ad_instproc my-method2 {-id:required {-flag:boolean true}} {
+ This is an instproc of Class Test merely for testing purposes...
+ @param id Some Id
+ @param flag Some flag
+} {
+ ns_log notice "hello world $id"
+}
+::Test ad_instproc -private my-method3 {-id:required {-flag:boolean true} -switch:switch x {y 1}} {
+ This is an instproc of Class Test merely for testing purposes...
+ @param id Some Id
+ @param flag Some flag
+ @param switch Switch to turn on or off depending on default
+ @param x First Operand
+ @param y Second Operand
+} {
+ ns_log notice "hello world $id"
+}
+
+Class ::SpecializedTest -superclass ::Test -ad_doc {
+ A Class defined as a subclass of ::Test for testing the
+ documentation stuff...
+}
Index: openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl,v
diff -u -N -r1.2.2.1 -r1.2.2.2
--- openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 15 Jan 2007 08:49:58 -0000 1.2.2.1
+++ openacs-4/packages/xotcl-core/tcl/05-db-procs.tcl 1 Aug 2007 21:39:32 -0000 1.2.2.2
@@ -6,45 +6,392 @@
@cvs-id $Id$
}
+
namespace eval ::xo::db {
+ ::xotcl::Object create require
- ::xotcl::Object require
+ require set postgresql_table_exists {select 1 from pg_tables where tablename = '$name'}
+ require set postgresql_view_exists {select 1 from pg_views where viewname = '$name'}
+ require set postgresql_index_exists {select 1 from pg_indexes where indexname = '$name'}
+ require set oracle_table_exists {select 1 from all_tables where table_name = '$name'}
+ require set oracle_view_exists {select 1 from all_views where view_name = '$name'}
+ require set oracle_index_exists {select 1 from all_indexes where index_name = '$name'}
+
require proc table {name definition} {
- if {![db_0or1row check-$name \
- "select 1 from pg_tables where tablename = '$name'"]} {
- db_dml create-$name "create table $name ($definition)"
+ if {[db_driverkey ""] eq "oracle"} {set name [string toupper $name]}
+ if {![db_0or1row [my qn ""] [subst [my set [db_driverkey ""]_table_exists]]]} {
+ #my log "--table $name does not exist, creating with $definition"
+ db_dml [my qn create-table-$name] "create table $name ($definition)"
}
}
require proc view {name definition} {
- if {![db_0or1row check-$name \
- "select 1 from pg_views where viewname = '$name'"]} {
- db_dml create-$name "create view $name AS $definition"
+ if {[db_driverkey ""] eq "oracle"} {set name [string toupper $name]}
+ if {![db_0or1row [my qn ""] [subst [my set [db_driverkey ""]_view_exists]]]} {
+ db_dml [my qn create-view-$name] "create view $name AS $definition"
}
}
+ if {[db_driverkey ""] eq "oracle"} {
+ proc mk_sql_constraint_name {table att suffix} {
+ set name ${table}_${att}_$suffix
+ if {[string length $name]>30} {
+ set sl [string length $suffix]
+ set name [string range ${table}_${att} 0 [expr {28 - $sl}]]_$suffix
+ }
+ return [string toupper $name]
+ }
+ } else {
+ proc mk_sql_constraint_name {table att suffix} {
+ set name ${table}_${att}_$suffix
+ return $name
+ }
+ }
+
require proc index {-table -col {-using ""} {-unique false}} {
set colpart $col
regsub -all ", *" $colpart _ colpart
set suffix [expr {$unique ? "un_idx" : "idx"}]
set uniquepart [expr {$unique ? "UNIQUE" : ""}]
- set name ${table}_${colpart}_$suffix
- if {![db_0or1row check_${name} \
- "select 1 from pg_indexes where indexname = '$name'"]} {
+ set name [::xo::db::mk_sql_constraint_name $table $colpart $suffix]
+ if {![db_0or1row [my qn ""] [subst [my set [db_driverkey ""]_index_exists]]]} {
set using [expr {$using ne "" ? "using $using" : ""}]
- db_dml create-$name \
+ db_dml [my qn create-index-$name] \
"create $uniquepart index $name ON $table $using ($col)"
}
}
- proc has_ltree {} {
+ require proc package name {
+ if {[info command ::${name}::*] eq ""} {
+ set dir [ns_info tcllib]/../packages/$name
+ foreach file [glob $dir/tcl/*-procs.tcl] {
+ uplevel #1 source $file
+ }
+ }
+ }
+
+ proc function_name {sql} {
+ if {[db_driverkey ""] eq "oracle"} {return [string map [list "__" .] $sql]}
+ return $sql
+ }
+
+ ad_proc has_ltree {} {
+ Check, whether ltree is available (postgres only)
+ } {
ns_cache eval xotcl_object_cache ::xo::has_ltree {
- if {[db_string check_ltree "select count(*) from pg_proc where proname = 'ltree_in'"] == 0} {
- return 0
+ if {[db_driverkey ""] eq "postgresql" &&
+ [db_string check_ltree "select count(*) from pg_proc where proname = 'ltree_in'"]} {
+ return 1
}
- return 1
+ return 0
}
}
+ # we create the sql object
+ ::xotcl::Object create sql
+
+
+ if {[db_driverkey ""] eq "postgresql"} {
+
+ # during load, we do not have "package_plsql_args" available yet, so we do it by hand
+ sql set all_package_functions {
+ select distinct
+ substring(function from 0 for position('__' in function)) as package_name,
+ substring(function from position('__' in function)+2) as object_name
+ from acs_function_args
+ }
+
+ sql proc map_datatype {type} {
+ switch -- $type {
+ long_text { set type text }
+ }
+ return $type
+ }
+ sql proc datatype_constraint {type table att} {return ""}
+
+ sql proc select {
+ -vars:required
+ -from:required
+ -where:required
+ {-groupby ""}
+ {-limit ""}
+ {-offset ""}
+ {-start ""}
+ {-orderby ""}
+ {-map_function_names false}
+ } {
+ set offset_clause [expr {$offset ne "" ? "OFFSET $offset" : ""}]
+ set limit_clause [expr {$limit ne "" ? "LIMIT $limit" : ""}]
+ set order_clause [expr {$orderby ne "" ? "ORDER BY $orderby" : ""}]
+ set group_clause [expr {$groupby ne "" ? "GROUP BY $groupby" : ""}]
+ return "SELECT $vars FROM $from WHERE $where $group_clause $order_clause $limit_clause"
+ }
+
+ sql proc date_trunc {field date} {
+ return "date_trunc('$field',$date)"
+ }
+ sql proc date_trunc_expression {field date date_string} {
+ return "date_trunc('$field',$date) = '$date_string'"
+ }
+
+ } else { ;# Oracle
+
+ sql set all_package_functions {
+ select distinct package_name, object_name
+ from user_arguments args
+ where args.position > 0 and package_name is not null
+ }
+
+ sql proc map_datatype {type} {
+ switch -- $type {
+ text { set type varchar2(4000) }
+ long_text { set type clob }
+ boolean { set type char(1) }
+ }
+ return $type
+ }
+ sql proc datatype_constraint {type table att} {
+ set constraint ""
+ switch $type {
+ boolean {
+ set cname [::xo::db::mk_sql_constraint_name $table $att _ck]
+ set constraint "constraint $cname check ($att in ('t','f'))"}
+ }
+ return $constraint
+ }
+
+ sql proc select {
+ -vars:required
+ -from:required
+ -where:required
+ {-groupby ""}
+ {-limit ""}
+ {-offset ""}
+ {-start ""}
+ {-orderby ""}
+ {-map_function_names false}
+ } {
+ # "-start" not used so far
+ set order_clause [expr {$orderby ne "" ? "ORDER BY $orderby" : ""}]
+ set group_clause [expr {$groupby ne "" ? "GROUP BY $groupby" : ""}]
+ if {$map_function_names} {set vars [::xo::db::function_name $vars]}
+ set sql "SELECT $vars FROM $from WHERE $where $group_clause"
+ if {$limit ne "" || $offset ne ""} {
+ if {$offset eq ""} {
+ set limit_clause "ROWNUM <= $limit"
+ } elseif {$limit eq ""} {
+ set limit_clause "ROWNUM >= $offset"
+ } else {
+ set limit_clause "ROWNUM BETWEEN $offset and [expr {$offset+$limit}]"
+ }
+ # for pagination, we will need an "inner" sort, such as
+ # SELECT * FROM (SELECT ...., ROW_NUMBER() OVER (ORDER BY ...) R FROM table) WHERE R BETWEEN 0 and 100
+ set sql "SELECT * FROM ($sql $order_clause) WHERE $limit_clause"
+ } else {
+ append sql " " $order_clause
+ }
+ my log "--returned sql = $sql"
+ return $sql
+ }
+ sql proc date_trunc {field date} {
+ return "to_char(trunc($date,'$field'), 'YYYY-MM-DD HH24:MI:SS')"
+ }
+ sql proc date_trunc_expression {field date date_string} {
+ return "trunc($date,'$field') = trunc(to_date('$date_string','YYYY-MM-DD'),'$field')"
+ }
+ }
+ sql proc since_interval_condition {var interval} {
+ set since [clock format [clock scan "-$interval"] -format "%Y-%m-%d %T"]
+ return "$var > TO_TIMESTAMP('$since','YYYY-MM-DD HH24:MI:SS')"
+ }
}
+namespace eval ::xo::db {
+ Class create DbPackage
+
+ # Some stored procs like content_item__new do currently not define null default values.
+ # Therefore, we need - temporary - this ugly redundancy to keep
+ # :required passing and to allow the xowiki regression test to run.
+ # The correct fix is to define the correct default values in the
+ # database with define_function_args()
+ DbPackage array set defaults {
+ "content_item__new" {RELATION_TAG null DESCRIPTION null TEXT null
+ CREATION_IP null NLS_LANGUAGE null LOCALE null CONTEXT_ID null
+ DATA null TITLE null ITEM_ID null
+ }
+ "content_type__create_attribute" {
+ DEFAULT_VALUE null SORT_ORDER null PRETTY_PLURAL null
+ }
+ "content_type__drop_type" {
+ DROP_CHILDREN_P f DROP_TABLE_P f DROP_OBJECTS_P f
+ }
+ }
+
+ DbPackage instproc sql-arguments {sql package_name object_name} {
+ my array unset defined
+ my set function_args [db_list_of_lists [my qn get_function_params] $sql]
+ set psql_args [list]
+ my set arg_order [list]
+ foreach arg [my set function_args] {
+ foreach {arg_name default_value} $arg break
+ lappend psql_args \$_$arg_name
+ my lappend arg_order $arg_name
+ my set defined($arg_name) $default_value
+ }
+ if {[[self class] exists defaults(${package_name}__$object_name)]} {
+ set prototype_args [[self class] set defaults(${package_name}__$object_name)]
+ foreach {arg_name default_value} $prototype_args {
+ if {![my exists defined($arg_name)]} {
+ lappend psql_args \$_$arg_name
+ my lappend arg_order $arg_name
+ }
+ }
+ my array set defined $prototype_args
+ }
+ return [join $psql_args ", "]
+ }
+
+ DbPackage instproc psql-postgresql {package_name object_name full_statement_name} {
+ set psql_args [my sql-arguments {
+ select args.arg_name, args.arg_default
+ from acs_function_args args
+ where args.function = upper(:package_name) || '__' || upper(:object_name)
+ order by function, arg_seq
+ } $package_name $object_name]
+ my set sql [subst {
+ select ${package_name}__${object_name}($psql_args)
+ }]
+ #return {ns_pg_bind 0or1row $db $sql}
+ return {ns_set value [ns_pg_bind 0or1row $db $sql] 0}
+ }
+
+ DbPackage instproc psql-oracle {package_name object_name full_statement_name} {
+ #
+ # in Oracle, we have to distinguish between functions and procs
+ #
+ set is_function [db_0or1row [my qn is_function] {
+ select 1 from dual
+ where exists (select 1 from user_arguments where
+ package_name = upper(:package_name)
+ and object_name = upper(:object_name)
+ and position = 0)
+ }]
+ # In Oracle, args.default_value appears to be defunct and useless.
+ # for now, we simply return "null" as a constant, otherwise the
+ # argument would be required
+ set psql_args [my sql-arguments {
+ select args.argument_name, 'unknown'
+ from user_arguments args
+ where args.position > 0
+ and args.object_name = upper(:object_name)
+ and args.package_name = upper(:package_name)
+ order by args.position
+ } $package_name $object_name]
+ if {$is_function} {
+ my set sql [subst {BEGIN :1 := ${package_name}.${object_name}(\$sql_args); END;}]
+ return {ns_ora exec_plsql_bind $db $sql 1 ""}
+ } else {
+ my set sql [subst {BEGIN ${package_name}.${object_name}(\$sql_args); END;}]
+ #return {ns_set value [ns_ora select $db $sql] 0}
+ return {ns_ora dml $db $sql}
+ }
+ }
+
+ DbPackage instproc proc_body-postgresql {} {
+ return {
+ #defined: [my array get defined]
+ foreach var \[list [my set arg_order]\] {
+ set varname \[string tolower $var\]
+ if {\[info exists $varname\]} {
+ set $var \[set $varname\]
+ set _$var :$var
+ } else {
+ set _$var null
+ }
+ }
+ set sql "[my set sql]"
+ db_with_handle -dbn $dbn db {
+ #my log "sql=$sql, sql_command=[set sql_command]"
+ return \[ [set sql_command] \]
+ }
+ }
+ }
+
+ DbPackage instproc proc_body-oracle {} {
+ return {
+ #defined: [my array get defined]
+ set sql_args \[list\]
+ foreach var \[list [my set arg_order]\] {
+ set varname \[string tolower $var\]
+ if {\[info exists $varname\]} {
+ lappend sql_args "$varname => :$varname"
+ }
+ }
+ set sql_args \[join $sql_args ,\]
+ set sql "[my set sql]"
+ db_with_handle -dbn $dbn db {
+ #my log "sql=$sql, sql_command=[set sql_command]"
+ return \[ [set sql_command] \]
+ }
+ }
+ }
+
+ DbPackage instproc dbproc_nonposargs {object_name} {
+ #
+ # This method compiles a stored procedure into a xotcl method
+ # using a classic nonpositional argument style interface.
+ #
+ # The current implementation should work on postgres and oracle (not tested)
+ # but will not work, when a single openacs instance want to talk to
+ # postgres and oracle simultaneously. Not sure, how important this is...
+ #
+ if {$object_name eq "set"} {
+ my log "We cannot handle object_name = '$object_name' in this version"
+ return
+ }
+ set package_name [namespace tail [self]]
+ set statement_name [my qn $package_name-$object_name]
+ set sql_command [my psql-[db_driverkey ""] $package_name $object_name $statement_name]
+ set proc_body [my proc_body-[db_driverkey ""]]
+
+ set nonposarg_list [list [list -dbn ""]]
+ foreach arg_name [my set arg_order] {
+ set default_value [my set defined($arg_name)]
+ set required [expr {$default_value eq "" ? ":required" : ""}]
+ # special rule for DBN ... todo: proc has to handle this as well
+ set nonposarg_name [expr {$arg_name eq "DBN" ? "DBN" : [string tolower $arg_name]}]
+ lappend nonposarg_list -$nonposarg_name$required
+ }
+ #my log "-- define $object_name $nonposarg_list"
+
+ my ad_proc $object_name $nonposarg_list {} [subst -novariables $proc_body]
+ }
+
+ DbPackage instproc unknown {m args} {
+ error "Error: unknown database method $m for dbpackage [self]"
+ }
+
+ DbPackage proc create_all_functions {} {
+ db_foreach [my qn ""] [::xo::db::sql set all_package_functions] {
+ #if {![my isobject $package_name]} { DbPackage create $package_name }
+ #$package_name dbproc_exportvars $object_name
+ set class_name ::xo::db::sql::[string tolower $package_name]
+ if {![my isobject $class_name]} { DbPackage create $class_name }
+ $class_name dbproc_nonposargs [string tolower $object_name]
+ }
+ }
+
+ DbPackage create_all_functions
+
+ ad_proc tcl_date {timestamp tz_var} {
+ Convert the time stamp (coming from the database) into a format, which
+ can be passed to Tcl's "clock scan".
+ } {
+ upvar $tz_var tz
+ set tz 00
+ regexp {^([^.]+)[.][0-9]+(.*)$} $timestamp _ timestamp tz
+ return $timestamp
+ }
+}
+
+
Index: openacs-4/packages/xotcl-core/tcl/05-doc-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/05-doc-procs.tcl,v
diff -u -N
--- openacs-4/packages/xotcl-core/tcl/05-doc-procs.tcl 29 Dec 2006 11:04:16 -0000 1.10
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,335 +0,0 @@
-ad_library {
- XOTcl API for api browser, defines the methods
- ad_proc (for object specific methods),
- ad_instproc (for tradional methods) and
- ad_odc (for documenting classes). Syntax for the methods
- ad_proc and ad_instproc is like oacs ad_proc, ad_doc
- receives one argument, similar to ad_library.
-
- @author Gustaf Neumann
- @creation-date 2005-05-13
- @cvs-id $Id: 05-doc-procs.tcl,v 1.10 2006/12/29 11:04:16 gustafn Exp $
-}
-
-# Per default, the content of the ::xotcl:: namespace is not serialized;
-# so we add the specified methods explizitely to the export list
-::Serializer exportMethods {
- ::xotcl::Object instproc ad_proc
- ::xotcl::Object instproc ad_forward
- ::xotcl::Class instproc ad_instproc
- ::xotcl::Class instproc ad_instforward
- ::xotcl::Object instproc ad_doc
- ::xotcl::Object instproc __api_make_doc
- ::xotcl::Object instproc __api_make_forward_doc
-}
-::Serializer exportObjects {
- ::xotcl::api
-}
-
-::xotcl::Object create ::xotcl::api \
- -proc isclass {scope obj} {
- expr {$scope eq "" ?
- [::xotcl::Object isclass $obj] :
- [$scope do ::xotcl::Object isclass $obj]}
- } -proc isobject {scope obj} {
- expr {$scope eq "" ?
- [::xotcl::Object isobject $obj] :
- [$scope do ::xotcl::Object isobject $obj]}
- } -proc scope {} {
- if {[info exists ::xotcl::currentThread]} {
- # we are in an xotcl thread; the body won't be accessible directly
- return $::xotcl::currentThread
- }
- return ""
-
- } -proc scope_from_object_reference {scope_var object_var} {
- upvar $scope_var scope $object_var object
- set scope ""
- regexp {^(.+) do (.+)$} $object match scope object
-
- } -proc scope_from_proc_index {proc_index} {
- set scope ""
- regexp {^(.+) .+ (inst)?proc (.+)$} $proc_index match scope
- return $scope
-
- } -proc inscope {scope args} {
- expr {$scope eq "" ? [eval $args] : [eval $scope do $args]}
-
- } -proc script_name {scope} {
- #set kind [expr {[my istype ::xotcl::Class] ? "Class" : "Object"}]
- #return "$scope$kind [self]"
- set script [info script]
- if {$script eq "" && [info exists ::xotcl::currentScript]} {
- set script $::xotcl::currentScript
- }
- set root_dir [nsv_get acs_properties root_directory]
- set root_length [string length $root_dir]
- if { $root_dir eq [string range $script 0 [expr {$root_length - 1}]]} {
- set script [string range $script [expr {$root_length + 1}] end]
- }
- return $script
-
- } -proc object_link {{-noimg:boolean off} scope obj} {
- set link ""
- if {$noimg} {
- return "$link$obj "
- } else {
- return "$obj$link "
- }
-
- } -proc object_url {{-show_source 0} {-show_methods 1} scope obj} {
- set object [expr {$scope eq "" ? $obj : "$scope do $obj"}]
- return [export_vars -base /xotcl/show-object {object show_source show_methods}]
- } -proc object_index {scope obj} {
- set kind [expr {[my isclass $scope $obj] ? "Class" : "Object"}]
- return "$scope$kind $obj"
-
- } -proc proc_index {scope obj instproc proc_name} {
- if {$scope eq ""} {
- return "$obj $instproc $proc_name"
- } else {
- return "$scope $obj $instproc $proc_name"
- }
-
- } -proc source_to_html {{-width 100} string} {
- set lines [list]
- foreach l [split $string \n] {
- while {[string length $l] > $width} {
- set pos [string last " \{" $l $width]
- if {$pos>10} {
- lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
- set l " [string range $l $pos end]"
- } else {
- # search for a match right of the target
- set pos [string first " \{" $l $width]
- if {$pos>10} {
- lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
- set l " [string range $l $pos end]"
- } else {
- # last resort try to split around spaces
- set pos [string last " " $l $width]
- if {$pos>10} {
- lappend lines "[string range $l 0 [expr {$pos-1}]] \\"
- set l " [string range $l $pos end]"
- } else {
- break
- }
- }
- }
- }
- lappend lines $l
- }
- set string [join $lines \n]
- set html [ad_quotehtml $string]
- regsub -all {(\n[\t ]*)(\#[^\n]*)} $html \\1\\2 html
- return "
$html "
- }
-
-
-
-
-::xotcl::Object instproc __api_make_doc {inst proc_name} {
- upvar doc doc private private public public deprecated deprecated
- if {$doc eq ""} {
- set doc_elements(main) ""
- } else {
- ad_parse_documentation_string $doc doc_elements
- }
- set defaults [list]
- foreach a [my info ${inst}args $proc_name] {
- if {[my info ${inst}default $proc_name $a d]} {lappend defaults $a $d}
- }
- set public [expr {$private ? false : true}]
- set doc_elements(public_p) $public
- set doc_elements(private_p) $private
- set doc_elements(deprecated_p) $deprecated
- set doc_elements(varargs_p) [expr {[lsearch args [my info ${inst}args $proc_name]]>-1}]
- set doc_elements(flags) [list]
- set doc_elements(switches) [list]
- foreach f [my info ${inst}nonposargs $proc_name] {
- set pair [split [lindex $f 0 0] :]
- set sw [string range [lindex $pair 0] 1 end]
- lappend doc_elements(switches) $sw
- lappend doc_elements(flags) $sw [lindex $pair 1]
- #my log "default_value $proc_name: $sw -> '[lindex $f 1]' <$pair/$f>"
- if {[lindex $pair 1] eq "switch" && [lindex $f 1] eq ""} {
- set default "false"
- } else {
- set default [lindex $f 1]
- }
- #my log "default_value $proc_name: $sw -> 'default' <$pair/$f>"
- lappend defaults $sw $default
- }
- set doc_elements(default_values) $defaults
- set doc_elements(positionals) [my info ${inst}args $proc_name]
- # argument documentation finished
- set scope [::xotcl::api scope]
- set doc_elements(script) [::xotcl::api script_name $scope]
- set proc_index [::xotcl::api proc_index $scope [self] ${inst}proc $proc_name]
- if {![nsv_exists api_proc_doc $proc_index]} {
- nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
- }
- #my log "doc_elements=[array get doc_elements]"
- #my log "SETTING api_proc_doc '$proc_index'"
- nsv_set api_proc_doc $proc_index [array get doc_elements]
-}
-
-::xotcl::Object instproc __api_make_forward_doc {inst method_name} {
- upvar doc doc private private public public deprecated deprecated
- if {$doc eq ""} {
- set doc_elements(main) ""
- } else {
- ad_parse_documentation_string $doc doc_elements
- #my log "doc_elements=[array get doc_elements]"
- }
- set defaults [list]
- set public [expr {$private ? false : true}]
- set doc_elements(public_p) $public
- set doc_elements(private_p) $private
- set doc_elements(deprecated_p) $deprecated
- set doc_elements(varargs_p) false
- set doc_elements(flags) [list]
- set doc_elements(switches) [list]
- set doc_elements(default_values) [list]
- set doc_elements(positionals) [list]
- # argument documentation finished
- set scope [::xotcl::api scope]
- set doc_elements(script) [::xotcl::api script_name $scope]
- set proc_index [::xotcl::api proc_index $scope [self] ${inst}forward $method_name]
- if {![nsv_exists api_proc_doc $proc_index]} {
- nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
- }
- #my log "doc_elements=[array get doc_elements]"
- #my log "SETTING api_proc_doc '$proc_index'"
- nsv_set api_proc_doc $proc_index [array get doc_elements]
-}
-
-::xotcl::Object instproc ad_proc {
- {-private:switch false}
- {-deprecated:switch false}
- {-warn:switch false}
- {-debug:switch false}
- proc_name arguments doc body} {
- uplevel [list [self] proc $proc_name $arguments $body]
- my __api_make_doc "" $proc_name
- }
-
-::xotcl::Object instproc ad_forward {
- {-private:switch false}
- {-deprecated:switch false}
- {-warn:switch false}
- {-debug:switch false}
- method_name doc args} {
- uplevel [self] forward $method_name $args
- my __api_make_forward_doc "" $method_name
- }
-
-::xotcl::Class instproc ad_instproc {
- {-private:switch false}
- {-deprecated:switch false}
- {-warn:switch false}
- {-debug:switch false}
- proc_name arguments doc body} {
- uplevel [list [self] instproc $proc_name $arguments $body]
- my __api_make_doc inst $proc_name
- }
-
-::xotcl::Object instproc ad_instforward {
- {-private:switch false}
- {-deprecated:switch false}
- {-warn:switch false}
- {-debug:switch false}
- method_name doc args} {
- uplevel [self] instforward $method_name $args
- my __api_make_forward_doc inst $method_name
- }
-
-
-
-::xotcl::Object instproc ad_doc {doc_string} {
- ad_parse_documentation_string $doc_string doc_elements
- set scope [::xotcl::api scope]
- set doc_elements(script) [::xotcl::api script_name $scope]
- set proc_index [::xotcl::api object_index $scope [self]]
-
- #if {![nsv_exists api_proc_doc $proc_index]} {
- # nsv_lappend api_proc_doc_scripts $doc_elements(script) $proc_index
- #}
- set doc_elements(public_p) true
- set doc_elements(private_p) false
- set doc_elements(varargs_p) false
- set doc_elements(deprecated_p) false
- set doc_elements(default_values) ""
- set doc_elements(switches) ""
- set doc_elements(positionals) ""
- set doc_elements(flags) ""
- nsv_set api_proc_doc $proc_index [array get doc_elements]
- nsv_set api_library_doc \
- $proc_index \
- [array get doc_elements]
-
- set file_index $doc_elements(script)
-
- if {[nsv_exists api_library_doc $file_index]} {
- array set elements [nsv_get api_library_doc $file_index]
- }
- set oldDoc [expr {[info exists elements(main)] ? \
- [lindex $elements(main) 0] : ""}]
- set prefix "This file defines the following Objects and Classes"
- set entry [::xotcl::api object_link $scope [self]]
- if {![string match *$prefix* $oldDoc]} {
- append oldDoc "$prefix: $entry"
- } else {
- append oldDoc ", $entry"
- }
- set elements(main) [list $oldDoc]
- #my log "elements = [array get elements]"
- nsv_set api_library_doc $file_index [array get elements]
-}
-
-
-Class ::Test -ad_doc {
- Test Class for the documentation of
- Classes
,
- Objects
,
- instprocs
, and
- procs
.
- @author Gustaf Neumann
- @cvs-id $Id: 05-doc-procs.tcl,v 1.10 2006/12/29 11:04:16 gustafn Exp $
-}
-::Test ad_proc my-class-specific-proc {x y} {
- This is a proc of Class Test merely for testing purposes...
- @param x First Operand
- @param y Second Operand
-} {
- ns_log notice "hello world $x $y"
-}
-
-::Test ad_instproc my-method {-id:required} {
- This is an instproc of Class Test merely for testing purposes...
- @param id Some Id
-} {
- ns_log notice "hello world $id"
-}
-::Test ad_instproc my-method2 {-id:required {-flag:boolean true}} {
- This is an instproc of Class Test merely for testing purposes...
- @param id Some Id
- @param flag Some flag
-} {
- ns_log notice "hello world $id"
-}
-::Test ad_instproc -private my-method3 {-id:required {-flag:boolean true} -switch:switch x {y 1}} {
- This is an instproc of Class Test merely for testing purposes...
- @param id Some Id
- @param flag Some flag
- @param switch Switch to turn on or off depending on default
- @param x First Operand
- @param y Second Operand
-} {
- ns_log notice "hello world $id"
-}
-
-Class ::SpecializedTest -superclass ::Test -ad_doc {
- A Class defined as a subclass of ::Test for testing the
- documentation stuff...
-}
Index: openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl-old
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/10-recreation-procs.tcl-old,v
diff -u -N
--- openacs-4/packages/xotcl-core/tcl/10-recreation-procs.tcl-old 30 Dec 2005 00:04:44 -0000 1.4
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,161 +0,0 @@
-ad_library {
- Support for the recreation of classes objects without
- destroying foreign references. Normally, when a class
- definition is reloaded, the class is destroyed and created
- again with the same name. During the destruction of a class
- several references to this class are removed (e.g. in a
- class hierarchy, the relation from instances to this class, etc.).
- XOTcl provides support for altering this behavior through
- the recreate method.
-
- @author Gustaf Neumann
- @creation-date 2005-05-13
- @cvs-id $Id: 10-recreation-procs.tcl-old,v 1.4 2005/12/30 00:04:44 gustafn Exp $
-}
-
-if {![::xotcl::Object isclass ::xotcl::RecreationClass]} {
- ::xotcl::Class create ::xotcl::RecreationClass -ad_doc {
-
This meta-class controlls the behavior of classes (and optionally
- their instances), when the classes (or their instances) are
- overwritten by same named new objects; we call this situation
- a recreate of an object.
-
- Normally, when files with e.g. class definitions are sourced,
- the classes and objects are newly defined. When e.g. class
- definitions exists already in this file, these classes are
- deleted first before they are newly created. When a class is
- deleted, the instances of this class are changed into
- instances of class ::xotcl::Object.
-
- This can be a problem when the class instances are not
- reloaded and when they should survife the redefintion with the
- same class relationships. Therefore we define a
- meta class RecreationClass, which can be used to parameterize
- the behavior on redefinitions. Alternatively, Classes or objects
- could provide their own recreate methods.
-
- Per default, this meta-class handles only the class redefintion
- case and does only a reconfigure on the class object (in order
- to get e.g. ad_doc updated).
- The following parameters are defined:
-
- reconfigure: reconfigure class (default 1)
- reinit: run init after configure for this class (default unset)
- instrecreate: handle recreate of class instances (default unset)
- When this flag is set to 0, instreconfigure and instreinit are ignored.
- instreconfigure: reconfigure instances of this class (default 1)
- instreinit: re-init instances of this class (default unset)
-
- } -parameter {
- {reconfigure 1}
- {reinit}
- {instrecreate}
- {instreconfigure 1}
- {instreinit}
- } -superclass ::xotcl::Class \
- -instproc recreate {obj args} {
- my log "### recreateclass instproc $obj <$args>"
- # the minimal reconfiguration is to set the class and remove methods
- $obj class [self]
- foreach p [$obj info procs] {$obj proc $p {} {}}
- if {![my exists instrecreate]} {
- #my log "### no instrecreate for $obj <$args>"
- next
- return
- }
- if {[my exists instreconfigure]} {
- # before we set defaults, we must unset vars
- foreach var [$obj info vars] {$obj unset $var}
- set pcl [my info parameterclass]
- # set defaults and run configure
- $pcl searchDefaults $obj
- eval $obj configure $args
- #my log "### instproc recreate $obj + configure $args ..."
- }
- if {[my exists instreinit]} {
- #my log "### instreinit for $obj <$args>"
- eval $obj init
- #my log "### instproc recreate $obj + init ..."
- }
- } -proc recreate {obj args} {
- my log "### recreateclass proc $obj <$args>"
- # the minimal reconfiguration is to set the class and remove methods
- $obj class [self]
- foreach p [$obj info instprocs] {$obj instproc $p {} {}}
- if {[my exists reconfigure]} {
- # before we set defaults, we must unset vars
- foreach var [$obj info vars] {$obj unset $var}
- set pcl [my info parameterclass]
- $pcl searchDefaults $obj
- # set defaults and run configure
- eval $obj configure $args
- }
- if {[my exists reinit]} {
- eval $obj init
- }
- }
-
- ::Serializer exportObjects {
- ::xotcl::RecreationClass
- }
-}
-
-Class ad_proc recreate {obj args} {
- The re-definition of recreate makes reloading of class definitions via
- apm possible, since the foreign keys of the class relations
- to these classes survive these calls. One can define specialized
- versions of this for certain classes or use ::xotcl::RecreationClass.
-
- Class proc recreate is called on the class level, while
- Class instproc recreate is called on the instance level.
-
- @param obj name of the object to be recreated
- @param args arguments passed to recreate (might contain parameters)
-} {
- # clean on the class level
- #my log "proc recreate $obj $args"
- foreach p [$obj info instprocs] {$obj instproc $p {} {}}
- $obj instmixin set {}
- $obj instfilter set {}
- next ; # clean next on object level
-}
-Class ad_instproc recreate {obj args} {
- The re-definition of recreate makes reloading of class definitions via
- apm possible, since the foreign keys of the class relations
- to these classes survive these calls. One can define specialized
- versions of this for certain classes or use ::xotcl::RecreationClass.
-
- Class proc recreate is called on the class level, while
- Class instproc recreate is called on the instance level.
-
- @param obj name of the object to be recreated
- @param args arguments passed to recreate (might contain parameters)
-} {
- # clean on the object level
- my log "+++ instproc recreate $obj <$args> old class = [$obj info class], new class = [self]"
- set cl [self]
- $obj class $cl
- foreach p [$obj info procs] {$obj proc $p {} {}}
- foreach c [$obj info children] {
- my log "recreate destroy <$c destroy"
- $c destroy
- }
- foreach var [$obj info vars] {$obj unset $var}
- $obj mixin set {}
- $obj filter set {}
- set pcl [$cl info parameterclass]
- $pcl searchDefaults $obj
- #my log "+++ recreate calling $obj configure $args"
- set pos [eval $obj configure $args]
- #my log "+++ recreate instproc configure returns $pos"
- if {[lsearch -exact $args -init] == -1} {
- incr pos -1
- #my log "+++ $obj init [lrange $args 0 $pos]"
- eval $obj init [lrange $args 0 $pos]
- }
-}
-
-::Serializer exportMethods {
- ::xotcl::Class instproc recreate
- ::xotcl::Class proc recreate
-}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl,v
diff -u -N -r1.7.2.1 -r1.7.2.2
--- openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl 15 Jan 2007 08:49:58 -0000 1.7.2.1
+++ openacs-4/packages/xotcl-core/tcl/20-Ordered-Composite-procs.tcl 1 Aug 2007 21:39:32 -0000 1.7.2.2
@@ -61,7 +61,9 @@
# destroy all children of the ordered composite
if {[my exists __children]} {
#my log "--W destroying children [my set __children]"
- foreach c [my set __children] { $c destroy }
+ foreach c [my set __children] {
+ if {[my isobject $c]} {$c destroy}
+ }
}
#show_stack;my log "--W children murdered, now next, chlds=[my info children]"
namespace eval [self] {namespace forget *} ;# for pre 1.4.0 versions
@@ -135,5 +137,19 @@
}
}
}
+
+ Class OrderedComposite::MethodCompare
+ OrderedComposite::MethodCompare instproc __compare {a b} {
+ set by [my set __orderby]
+ set x [$a $by]
+ set y [$b $by]
+ if {$x < $y} {
+ return -1
+ } elseif {$x > $y} {
+ return 1
+ } else {
+ return 0
+ }
+ }
}
Index: openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl,v
diff -u -N -r1.10 -r1.10.2.1
--- openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl 15 Sep 2006 16:33:06 -0000 1.10
+++ openacs-4/packages/xotcl-core/tcl/30-widget-procs.tcl 1 Aug 2007 21:39:32 -0000 1.10.2.1
@@ -39,16 +39,27 @@
set ::xo::acs_lang_url [apm_package_url_from_key acs-lang]admin
- proc localize text {
+ proc localize {text {inline 0}} {
+ #ns_log notice "--local $text $inline"
if {![my exists __localizer]} {
my set __localizer [list]
}
if {[string first \x002 $text] == -1} {
return $text
} else {
set return_text ""
+ if {$inline} {
+ # Attempt to move all message keys outside of tags
+ while { [regsub -all {(<[^>]*)(\x002\(\x001[^\x001]*\x001\)\x002)([^>]*>)} $text {\2\1\3} text] } {}
+
+ # Attempt to move all message keys outside of ... statements
+ regsub -all -nocase {(]*>[^<]*)(\x002\(\x001[^\x001]*\x001\)\x002)([^<]* ]*>)} $text {\2\1\3} text
+
+ while { [regsub -all -nocase {(]*>[^<]*)(\x002\(\x001[^\x001]*\x001\)\x002)} $text {\2\1} text] } {}
+ }
+
while {[regexp {^([^\x002]*)\x002\(\x001([^\x001]*)\x001\)\x002(.*)$} $text _ \
- before key text]} {
+ before key text]} {
append return_text $before
foreach {package_key message_key} [split $key .] break
set url [export_vars -base $::xo::acs_lang_url/edit-localized-message {
@@ -67,7 +78,12 @@
}]
set type missing
}
- my lappend __localizer [::xo::Localizer new -type $type -key $key -url $url]
+ if {!$inline} {
+ my lappend __localizer [::xo::Localizer new -type $type -key $key -url $url]
+ } else {
+ set l [::xo::Localizer new -type $type -key $key -url $url]
+ append return_text [$l asHTML]
+ }
}
append return_text $text
return $return_text
@@ -134,7 +150,11 @@
#
proc get_user_name {uid} {
if {$uid ne "" && $uid != 0} {
- acs_user::get -user_id $uid -array user
+ if {[catch {acs_user::get -user_id $uid -array user}]} {
+ # we saw some strange cases, where after a regression,
+ # a user_id was present, which was already deleted...
+ return nobody
+ }
return "$user(first_names) $user(last_name)"
} else {
return nobody
@@ -144,13 +164,15 @@
#
# define an abstract table
#
-
Class Table -superclass OrderedComposite \
- -parameter {{no_data "No Data"} {renderer TABLE2}}
+ -parameter [expr {[apm_version_names_compare [ad_acs_version] 5.3.0] == 1 ?
+ {{no_data "No Data"} {renderer TABLE3}} :
+ {{no_data "No Data"} {renderer TABLE2}}
+ }]
Table instproc destroy {} {
#my log "-- "
- foreach c {__actions __columns} {
+ foreach c {:__bulkactions __actions __columns} {
#my log "-- namespace eval [self]::$c {namespace forget *}"
namespace eval [self]::$c {namespace forget *}
}
@@ -161,6 +183,11 @@
namespace eval $M {namespace import -force [self class]::*}
$M contains $cmd
}
+ Table instproc __bulkactions {cmd} {
+ set M [OrderedComposite create [self]::__bulkactions]
+ namespace eval $M {namespace import -force [self class]::*}
+ $M contains $cmd
+ }
Table instproc columns {cmd} {
set M [OrderedComposite create [self]::__columns]
namespace eval $M {namespace import -force [self class]::*}
@@ -177,7 +204,7 @@
}
Table instproc render_with {renderer trn_mixin} {
- #my log "--"
+ #my log "-- renderer=$renderer"
set cl [self class]
[self] mixin ${cl}::$renderer
foreach child [$cl info classchildren] {
@@ -199,19 +226,25 @@
Table instproc write_csv {} {
set output ""
set line [list]
+ my msg columns=[[self]::__columns children]
foreach column [[self]::__columns children] {
- set value [string map {\" \\\"} [$column name]]
+ set label [$column label]
+ if {[regexp {^#(.*)#$} $label _ message_key]} {
+ set label [_ $message_key]
+ }
+ set value [string map {\" \\\"} $label]
lappend line \"$value\"
}
append output [join $line ,] \n
foreach row [my children] {
set line [list]
foreach column [[self]::__columns children] {
- set value [string map {\" \\\"} [$row set [$column name]]]
+ set value [string map {\" \\\"} [$row set [$column set name]]]
lappend line \"$value\"
}
append output [join $line ,] \n
}
+ #ns_return 200 text/plain $output
ns_return 200 text/csv $output
}
@@ -253,6 +286,23 @@
return -[my name]
}
+ Class BulkAction \
+ -superclass ::xo::OrderedComposite::Child \
+ -parameter {name id {html {}}} \
+ -instproc actions {cmd} {
+ my init
+ set grandParent [[my info parent] info parent]
+ if {![my exists name]} {my set name [namespace tail [self]]}
+ set M [::xo::OrderedComposite create ${grandParent}::__bulkactions]
+ namespace eval $M {namespace import -force ::xo::Table::*}
+ $M contains $cmd
+ $M set __belongs_to [self]
+ $M set __identifier [my set name]
+ } \
+ -instproc get-slots {} {
+ ;
+ }
+
Class AnchorField \
-superclass ::xo::Table::Field \
-instproc get-slots {} {
@@ -269,7 +319,6 @@
-instproc get-slots {} {
set slots [list -[my name]]
lappend slots [list -[my name].src [my src]]
- lappend slots [list -[my name].href ""]
foreach att {width height border title alt} {
if {[my exists $att]} {
lappend slots [list -[my name].$att [my $att]]
@@ -280,33 +329,40 @@
return $slots
}
+ Class ImageAnchorField \
+ -superclass ::xo::Table::ImageField \
+ -instproc get-slots {} {
+ return [concat [next] -[my name].href ""]
+ }
+
Class ImageField_EditIcon \
- -superclass ImageField -parameter {
+ -superclass ImageAnchorField -parameter {
{src /resources/acs-subsite/Edit16.gif} {width 16} {height 16} {border 0}
{title "[_ xotcl-core.edit_item]"} {alt "edit"}
}
# for xotcl 1.4.0: {title [_ xotcl-core.edit_item]} {alt "edit"}
Class ImageField_AddIcon \
- -superclass ImageField -parameter {
+ -superclass ImageAnchorField -parameter {
{src /resources/acs-subsite/Add16.gif} {width 16} {height 16} {border 0}
{title "Add Item"} {alt "add"}
}
Class ImageField_ViewIcon \
- -superclass ImageField -parameter {
+ -superclass ImageAnchorField -parameter {
{src /resources/acs-subsite/Zoom16.gif} {width 16} {height 16} {border 0}
{title "View Item"} {alt "view"}
}
Class ImageField_DeleteIcon \
- -superclass ImageField -parameter {
+ -superclass ImageAnchorField -parameter {
{src /resources/acs-subsite/Delete16.gif} {width 16} {height 16} {border 0}
{title "Delete Item"} {alt "delete"}
}
# export table elements
- namespace export Field AnchorField Action ImageField \
- ImageField_EditIcon ImageField_ViewIcon ImageField_DeleteIcon ImageField_AddIcon
+ namespace export Field AnchorField Action ImageField ImageAnchorField \
+ ImageField_EditIcon ImageField_ViewIcon ImageField_DeleteIcon ImageField_AddIcon \
+ BulkAction
}
}
@@ -321,6 +377,9 @@
-instproc init_renderer {} {
#my log "--"
my set __rowcount 0
+ my set css.table-class list
+ my set css.tr.even-class list-even
+ my set css.tr.odd-class list-odd
}
TABLE instproc render-actions {} {
@@ -339,6 +398,27 @@
}
}
+ TABLE instproc render-bulkactions {} {
+ set bulkactions [[self]::__bulkactions children]
+ html::div -class "list-button-bar-bottom" {
+ html::t "Bulk-Actions:"
+ set bulkaction_container [[lindex $bulkactions 0] set __parent]
+ set name [$bulkaction_container set __identifier]
+
+ html::ul -class compact {
+ foreach ba $bulkactions {
+ html::li {
+ html::a -title [$ba tooltip] -class button -href # \
+ -onclick "acs_ListBulkActionClick('$name','[$ba url]'); return false;" \
+ {
+ html::t [$ba label]
+ }
+ }
+ }
+ }
+ }
+ }
+
TABLE instproc render-body {} {
html::tr -class list-header {
foreach o [[self]::__columns children] {
@@ -350,7 +430,10 @@
html::tr {html::td { html::t [my set no_data]}}
} else {
foreach line [my children] {
- html::tr -class [expr {[my incr __rowcount]%2 ? "list-odd" : "list-even" }] {
+ #my log "--LINE vars=[my info vars] cL: [[self class] info vars] r=[my renderer]"
+ html::tr -class [expr {[my incr __rowcount]%2 ?
+ [my set css.tr.odd-class] :
+ [my set css.tr.even-class] }] {
foreach field [[self]::__columns children] {
html::td [concat [list class list] [$field html]] {
$field render-data $line
@@ -363,9 +446,22 @@
TABLE instproc render {} {
if {![my isobject [self]::__actions]} {my actions {}}
- html::table -class list {
- my render-actions
- my render-body
+ if {![my isobject [self]::__bulkactions]} {my bulkactions {}}
+ set bulkactions [[self]::__bulkactions children]
+ if {$bulkactions eq ""} {
+ html::table -class [my set css.table-class] {
+ my render-actions
+ my render-body
+ }
+ } else {
+ set name [[self]::__bulkactions set __identifier]
+ html::form -name $name {
+ html::table -class [my set css.table-class] {
+ my render-actions
+ my render-body
+ }
+ my render-bulkactions
+ }
}
}
@@ -391,7 +487,11 @@
Class create TABLE::Field -superclass ::xo::Drawable
TABLE::Field instproc render-data {line} {
- html::t [$line set [my name]]
+ if {[$line exists [my name].richtext]} {
+ html::t -disableOutputEscaping [$line set [my name]]
+ } else {
+ html::t [$line set [my name]]
+ }
}
TABLE::Field instproc render {} {
@@ -432,7 +532,7 @@
set href [export_vars -base [ad_conn url] $query]
html::a -href $href -title $title {
html::t [my _ label]
- html::img -src $img -alt ""
+ html::img -src $img -alt "" -border 0
}
}
@@ -453,12 +553,43 @@
Class create TABLE::ImageField \
-superclass TABLE::Field \
-instproc render-data {line} {
- html::a -href [$line set [my name].href] -style "border-bottom: none;" {
- html::img [$line attlist [my name] {src width height border title alt}] {}
- }
- $line render_localizer
+ html::a -style "border-bottom: none;" {
+ html::img [$line attlist [my name] {src width height border title alt}] {}
+ }
+ $line render_localizer
}
+ Class create TABLE::ImageAnchorField \
+ -superclass TABLE::Field \
+ -instproc render-data {line} {
+ set href [$line set [my name].href]
+ if {$href ne ""} {
+ html::a -href $href -style "border-bottom: none;" {
+ html::img [$line attlist [my name] {src width height border title alt}] {}
+ }
+ $line render_localizer
+ }
+ }
+
+ Class create TABLE::BulkAction -superclass ::xo::Drawable
+ TABLE::BulkAction instproc render {} {
+ set name [my name]
+ #my msg [my serialize]
+ html::th -class list {
+ html::input -type checkbox -name __bulkaction \
+ -onclick "acs_ListCheckAll('$name', this.checked)" \
+ -title "Mark/Unmark all rows"
+ }
+ }
+ TABLE::BulkAction instproc render-data {line} {
+ #my msg [my serialize]
+ set name [my name]
+ set value [$line set [my id]]
+ html::input -type checkbox -name $name -value $value \
+ -id "$name,$value" \
+ -title "Mark/Unmark this row"
+ }
+
Class TABLE2 \
-superclass TABLE \
-instproc render-actions {} {
@@ -472,19 +603,49 @@
} \
-instproc render {} {
if {![my isobject [self]::__actions]} {my actions {}}
+ if {![my isobject [self]::__bulkactions]} {my __bulkactions {}}
+ set bulkactions [[self]::__bulkactions children]
html::div {
my render-actions
- html::div -class table {
- html::table -class list {my render-body}
- }
+ if {$bulkactions eq ""} {
+ html::div -class table {
+ html::table -class [my set css.table-class] {my render-body}
+ }
+ } else {
+ set name [[self]::__bulkactions set __identifier]
+ html::form -name $name {
+ html::div -class table {
+ html::table -class [my set css.table-class] {my render-body}
+ my render-bulkactions
+ }
+ }
+ }
}
}
+
Class create TABLE2::Action -superclass TABLE::Action
Class create TABLE2::Field -superclass TABLE::Field
Class create TABLE2::AnchorField -superclass TABLE::AnchorField
Class create TABLE2::ImageField -superclass TABLE::ImageField
-
+ Class create TABLE2::ImageAnchorField -superclass TABLE::ImageAnchorField
+ Class create TABLE2::BulkAction -superclass TABLE::BulkAction
+
+ Class TABLE3 \
+ -superclass TABLE2 \
+ -instproc init_renderer {} {
+ next
+ my set css.table-class list-table
+ my set css.tr.even-class even
+ my set css.tr.odd-class odd
+ }
+
+ Class create TABLE3::Action -superclass TABLE::Action
+ Class create TABLE3::Field -superclass TABLE::Field
+ Class create TABLE3::AnchorField -superclass TABLE::AnchorField
+ Class create TABLE3::ImageField -superclass TABLE::ImageField
+ Class create TABLE3::ImageAnchorField -superclass TABLE::ImageAnchorField
+ Class create TABLE3::BulkAction -superclass TABLE::BulkAction
}
Class TableWidget \
Index: openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl,v
diff -u -N -r1.3 -r1.3.2.1
--- openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl 14 Jul 2006 01:22:11 -0000 1.3
+++ openacs-4/packages/xotcl-core/tcl/40-thread-mod-procs.tcl 1 Aug 2007 21:39:32 -0000 1.3.2.1
@@ -12,7 +12,7 @@
When an instance of THREAD is created (e.g. t1),
an init-command is provided. e.g.:
- THREAD create t1 {
+ ::xotcl::THREAD create t1 {
Class Counter -parameter {{value 1}}
Counter instproc ++ {} {my incr value}
Counter c1
@@ -52,7 +52,7 @@
creates a Proxy for an object c1 in thread t1.
After this, c1 can be used like an local object.
- THREAD::Proxy c1 -attach t1
+ ::xotcl::THREAD::Proxy c1 -attach t1
set x [c1 ++]
The Proxy forwards all commands to the
@@ -85,9 +85,9 @@
::xotcl::Object setExitHandler {
#my log "EXITHANDLER of request thread [pid]"
- if {[catch {Proxy detachAll} m]} {
- #my log "EXITHANDLER error in detachAll $m"
- }
+ #if {[catch {::xotcl::THREAD::Proxy detachAll} m]} {
+ # #my log "EXITHANDLER error in detachAll $m"
+ #}
}
::Serializer exportObjects {
@@ -102,7 +102,7 @@
# -parameter {{persistent 0}}
Class create ::xotcl::THREAD \
- -parameter {{persistent 0}}
+ -parameter {{persistent 0} {lightweight 0}}
#Class create ::xotcl::THREAD \
# -parameter {{persistent 0}}
@@ -117,8 +117,20 @@
}
::xotcl::THREAD instproc init cmd {
- my instvar initcmd
- set initcmd {
+ my instvar initcmd
+ if {![ns_ictl epoch]} {
+ #ns_log notice "--THREAD init [self] no epoch"
+
+ # We are during initialization. For some unknown reasons, XOTcl
+ # is not available in newly created threads, so we have to care for it.
+ # We need only a partial initialization, to allow the exit handler
+ # to be defined.
+ set initcmd {
+ package req XOTcl
+ namespace import -force ::xotcl::*
+ }
+ }
+ append initcmd {
::xotcl::Object setExitHandler {
#my log "EXITHANDLER of slave thread SELF [pid]"
}
@@ -161,7 +173,7 @@
my log "thread terminated"
nsv_unset [self class] [self]
thread::mutex destroy [my set mutex]
- ns_log notice "mutex [my set mutex] destroyed"
+ my log "+++ mutex [my set mutex] destroyed"
}
}
next
@@ -186,14 +198,31 @@
#my check_blueprint
#my log "after lock"
if {![nsv_exists [self class] [self]]} {
- set tid [::thread::create]
+ if {[my lightweight]} {
+ my log "CREATE lightweight thread"
+ set tid [::thread::create -thin]
+ } else {
+ set tid [::thread::create]
+ }
nsv_set [self class] [self] $tid
if {[my persistent]} {
- my log "created new persistent [self class] as $tid pid=[pid]"
+ my log "--created new persistent [self class] as $tid pid=[pid]"
} else {
- my log "created new [self class] as $tid pid=[pid]"
+ my log "--created new [self class] as $tid pid=[pid]"
}
- ::thread::send $tid [my set initcmd]
+ #my log "--THREAD DO send [self] epoch = [ns_ictl epoch]"
+ if {[my lightweight]} {
+ } elseif {![ns_ictl epoch]} {
+ #ns_log notice "--THREAD send [self] no epoch"
+ # We are during initialization. For some unknown reasons, XOTcl
+ # is not available in newly created threads, so we have to care
+ # for full initialization, including xotcl blueprint.
+ _ns_savenamespaces
+ set initcmd [ns_ictl get]
+ }
+ append initcmd [my set initcmd]
+ #ns_log notice "INIT $initcmd"
+ ::thread::send $tid $initcmd
} else {
set tid [nsv_get [self class] [self]]
}
@@ -223,7 +252,7 @@
# create a sample persistent thread that can be acessed
# via request threads
-#THREAD create t0 {
+#::xotcl::THREAD create t0 {
# Class Counter -parameter {{value 1}}
# Counter instproc ++ {} {my incr value}
#
Index: openacs-4/packages/xotcl-core/tcl/bgdelivery-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/bgdelivery-procs.tcl,v
diff -u -N -r1.7 -r1.7.2.1
--- openacs-4/packages/xotcl-core/tcl/bgdelivery-procs.tcl 12 Dec 2006 19:09:26 -0000 1.7
+++ openacs-4/packages/xotcl-core/tcl/bgdelivery-procs.tcl 1 Aug 2007 21:39:32 -0000 1.7.2.1
@@ -11,6 +11,7 @@
ns_log notice "libthread does not appear to be available, NOT loading bgdelivery"
return
}
+#return ;# DONT COMMIT
# catch {ns_conn contentsentlength} alone does not work, since we do not have
# a connection yet, and the bgdelivery won't be activated
@@ -108,7 +109,79 @@
fconfigure [my channel] -translation binary
incr ::subscription_count
}
-} -persistent 1
+
+ Class ::HttpSpooler -parameter {channel {timeout 10000} {counter 0}}
+ ::HttpSpooler instproc init {} {
+ my set running 0
+ my set release 0
+ my set spooling 0
+ my set queue [list]
+ }
+ ::HttpSpooler instproc all_done {} {
+ catch {close [my channel]}
+ my log ""
+ my destroy
+ }
+ ::HttpSpooler instproc release {} {
+ # release indicates the when running becomes 0, the spooler is finished
+ my set release 1
+ if {[my set running] == 0} {my all_done}
+ }
+ ::HttpSpooler instproc done {reason request} {
+ my instvar running release
+ incr running -1
+ my log "--running $running"
+ $request destroy
+ if {$running == 0 && $release} {my all_done}
+ }
+ ::HttpSpooler instproc deliver {data request} {
+ my instvar spooling
+ my log "-- spooling $spooling"
+ if {$spooling} {
+ my log "--enqueue"
+ my lappend queue $data $request
+ } else {
+ #my log "--send"
+ set spooling 1
+ # puts -nonewline [my channel] $data
+ # my done
+ set filename [ns_tmpnam]
+ set fd [open $filename w]
+ fconfigure $fd -translation binary
+ puts -nonewline $fd $data
+ close $fd
+ set fd [open $filename]
+ fconfigure $fd -translation binary
+ fconfigure [my channel] -translation binary
+ fcopy $fd [my channel] -command \
+ [list [self] end-delivery $filename $fd [my channel] $request]
+ }
+ }
+ ::HttpSpooler instproc end-delivery {filename fd ch request bytes args} {
+ my instvar queue
+ my log "--- end of delivery of $filename, $bytes bytes written $args"
+ if {[catch {close $fd} e]} {ns_log notice "httpspool, closing file $filename, error: $e"}
+ my set spooling 0
+ if {[llength $queue]>0} {
+ my log "--dequeue"
+ set data [lindex $queue 0]
+ set req [lindex $queue 1]
+ set queue [lreplace $queue 0 1]
+ my deliver $data $req
+ }
+ my done delivered $request
+ }
+ ::HttpSpooler instproc add {-request {-post_data ""}} {
+ if {[regexp {http://([^/]*)(/.*)} $request _ host path]} {
+ set port 80
+ regexp {^([^:]+):(.*)$} $host _ host port
+ my incr running
+ xo::AsyncHttpRequest [self]::[my incr counter] \
+ -host $host -port $port -path $path \
+ -timeout [my timeout] -post_data $post_data -request_manager [self]
+ }
+ }
+} -persistent 1 ;# -lightweight 1
bgdelivery ad_forward running {
Interface to the background delivery thread to query the currently running deliveries.
@@ -170,4 +243,19 @@
bgdelivery proc send_to_subscriber {key msg} {
my do -async ::Subscriber broadcast $key $msg
-}
\ No newline at end of file
+}
+#####################################
+bgdelivery proc create_spooler {{-content_type text/plain} {-timeout 10000}} {
+ ns_write "HTTP/1.0 200 OK\r\nContent-type: $content_type\r\n\r\n"
+ set ch [ns_conn channel]
+ thread::transfer [my get_tid] $ch
+ my do ::HttpSpooler new -channel $ch -timeout $timeout
+}
+
+bgdelivery proc spooler_add_request {spooler request {post_data ""}} {
+ my log "-- do -async $spooler add -request $request"
+ my do -async $spooler add -request $request -post_data $post_data
+}
+bgdelivery proc spooler_release {spooler} {
+ my do -async $spooler release
+}
Index: openacs-4/packages/xotcl-core/tcl/chat-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/Attic/chat-procs.tcl,v
diff -u -N -r1.11 -r1.11.2.1
--- openacs-4/packages/xotcl-core/tcl/chat-procs.tcl 2 Dec 2006 19:07:01 -0000 1.11
+++ openacs-4/packages/xotcl-core/tcl/chat-procs.tcl 1 Aug 2007 21:39:32 -0000 1.11.2.1
@@ -39,7 +39,9 @@
set msg [ad_quotehtml $msg]
my log "-- msg=$msg"
- if {$get_new && [info command ::thread::mutex] ne ""} {
+ if {$get_new
+ && [info command ::thread::mutex] ne ""
+ && [info command ::bgdelivery] ne ""} {
# we could use the streaming interface
my broadcast_msg [Message new -volatile -time [clock seconds] \
-user_id $user_id -msg $msg -color $color]
Index: openacs-4/packages/xotcl-core/tcl/context-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/context-procs.tcl,v
diff -u -N -r1.6.2.1 -r1.6.2.2
--- openacs-4/packages/xotcl-core/tcl/context-procs.tcl 15 Jan 2007 08:49:58 -0000 1.6.2.1
+++ openacs-4/packages/xotcl-core/tcl/context-procs.tcl 1 Aug 2007 21:39:32 -0000 1.6.2.2
@@ -50,13 +50,17 @@
}
# get the query parameters (from the url)
+ #my log "--P processing actual query $actual_query"
foreach querypart [split $actual_query &] {
set name_value_pair [split $querypart =]
set att_name [ns_urldecode [lindex $name_value_pair 0]]
- set att_value [expr {[llength $name_value_pair] == 1 ? 1 :
- [ns_urldecode [lindex $name_value_pair 1]] }]
+ if {[llength $name_value_pair] == 1} {
+ set att_value 1
+ } else {
+ set att_value [ns_urldecode [lindex $name_value_pair 1]]
+ }
if {[info exists (-$att_name)]} {
- set passed_args(-$att_name) $att_value
+ lappend passed_args(-$att_name) $att_value
} elseif {$all_from_query} {
set queryparm($att_name) $att_value
}
@@ -99,6 +103,17 @@
#my log "--cc qp [array names queryparm] // $actual_query"
}
+ Context instproc query_parameter {name {default ""}} {
+ my instvar queryparm
+ return [expr {[info exists queryparm($name)] ? $queryparm($name) : $default}]
+ }
+ Context instproc exists_query_parameter {name} {
+ #my log "--qp my exists $name => [my exists queryparm($name)]"
+ my exists queryparm($name)
+ }
+ Context instproc get_all_query_parameter {} {
+ return [my array get queryparm]
+ }
Context ad_instproc export_vars {{-level 1}} {
Export the query variables
@@ -150,7 +165,6 @@
url
}
- # TODO code (in xinha, + css)
# TODO edit revision loop
ConnectionContext proc require {
@@ -161,7 +175,7 @@
{-actual_query " "}
} {
if {![info exists url]} {
- my log "--CONN ns_conn url"
+ #my log "--CONN ns_conn url"
set url [ns_conn url]
}
#my log "--i [self args]"
@@ -174,19 +188,19 @@
if {![my isobject ::xo::cc]} {
my create ::xo::cc \
-package_id $package_id \
- -parameter_declaration $parameter \
+ [list -parameter_declaration $parameter] \
-user_id $user_id \
-actual_query $actual_query \
-url $url
- #my log "--cc ::xo::cc created $url"
- ::xo::cc destroy_on_cleanup
+ #my msg "--cc ::xo::cc created $url [::xo::cc serialize]"
+ ::xo::cc destroy_on_cleanup
} else {
#my log "--cc ::xo::cc reused $url"
::xo::cc configure \
-package_id $package_id \
-url $url \
-actual_query $actual_query \
- -parameter_declaration $parameter
+ [list -parameter_declaration $parameter]
::xo::cc set_user_id $user_id
::xo::cc process_query_parameter
}
@@ -200,7 +214,7 @@
}
ConnectionContext instproc returnredirect {url} {
- my log "--rp"
+ #my log "--rp"
my set __continuation [list ad_returnredirect $url]
return ""
}
@@ -246,12 +260,21 @@
call ::permission::permission_p but avoid multiple calls in the same
session through caching in the connection context
} {
- #my log "--p [self args] [info exists party_id] "
if {![info exists party_id]} {
set party_id [my user_id]
#my log "--p party_id $party_id"
- #::xo::show_stack
if {$party_id == 0} {
+ set key permission($object_id,$privilege,$party_id)
+ if {[my exists $key]} {return [my set $key]}
+ set granted [permission::permission_p -party_id $party_id \
+ -object_id $object_id \
+ -privilege $privilege]
+ if {$granted} {
+ my set $key $granted
+ return $granted
+ }
+ # The permission is not granted for the public.
+ # We force the user to login
auth::require_login
return 0
}
@@ -270,27 +293,36 @@
# next
# }
- ConnectionContext instproc query_parameter {name {default ""}} {
- my instvar queryparm
- return [expr {[info exists queryparm($name)] ? $queryparm($name) : $default}]
- }
- ConnectionContext instproc exists_query_parameter {name} {
- #my log "--qp my exists $name => [my exists queryparm($name)]"
- my exists queryparm($name)
- }
- ConnectionContext instproc form_parameter {name {default ""}} {
+ ConnectionContext instproc get_all_form_parameter {} {
my instvar form_parameter
+ #array set form_parameter [ns_set array [ns_getform]]
+ foreach {att value} [ns_set array [ns_getform]] {
+ if {[info exists form_parameter($att)]} {
+ my set form_parameter_multiple($att) 1
+ }
+ lappend form_parameter($att) $value
+ }
+ }
+ ConnectionContext instproc form_parameter {name {default ""}} {
+ my instvar form_parameter form_parameter_multiple
if {![info exists form_parameter]} {
- array set form_parameter [ns_set array [ns_getform]]
+ my get_all_form_parameter
}
- return [expr {[info exists form_parameter($name)] ?
- $form_parameter($name) : $default}]
+ if {[info exists form_parameter($name)]} {
+ if {[info exists form_parameter_multiple($name)]} {
+ return $form_parameter($name)
+ } else {
+ return [lindex $form_parameter($name) 0]
+ }
+ } else {
+ return $default
+ }
}
ConnectionContext instproc exists_form_parameter {name} {
my instvar form_parameter
if {![info exists form_parameter]} {
- array set form_parameter [ns_set array [ns_getform]]
+ my get_all_form_parameter
}
my exists form_parameter($name)
}
@@ -335,8 +367,8 @@
init_url false requires the package_id to be specified and
a call to Package instproc set_url to complete initialization
} {
+ #my log "--i [self args], URL=$url, init_url=$init_url"
- #my log "--i [self args]"
if {$url eq "" && $init_url} {
#set url [ns_conn url]
#my log "--CONN ns_conn url"
@@ -363,7 +395,7 @@
} {
#my log "--R $package_id exists? [my isobject ::$package_id]"
if {![my isobject ::$package_id]} {
- #my log "--R we have to create ::$package_id"
+ #my log "--R we have to create ::$package_id //url='$url'"
if {$url ne ""} {
my create ::$package_id -url $url
} else {
@@ -384,14 +416,16 @@
PackageMgr create Package -parameter {
id
url
+ {context ::xo::cc}
package_url
+ package_key
instance_name
}
- Package instforward query_parameter ::xo::cc %proc
- Package instforward exists_query_parameter ::xo::cc %proc
- Package instforward form_parameter ::xo::cc %proc
- Package instforward exists_form_parameter ::xo::cc %proc
- Package instforward returnredirect ::xo::cc %proc
+ Package instforward query_parameter {%my set context} %proc
+ Package instforward exists_query_parameter {%my set context} %proc
+ Package instforward form_parameter {%my set context} %proc
+ Package instforward exists_form_parameter {%my set context} %proc
+ Package instforward returnredirect {%my set context} %proc
Package instproc get_parameter {attribute {default ""}} {
@@ -404,18 +438,31 @@
my instvar id url
set id [namespace tail [self]]
array set info [site_node::get_from_object_id -object_id $id]
- my package_url $info(url)
+ set package_url $info(url)
+ if {[ns_conn isconnected]} {
+ # in case of of host-node map, simplify the url to avoid redirects
+ # .... but ad_host works only, when we are connected.... TODO: solution for syndication
+ set root [root_of_host [ad_host]]
+ regexp "^${root}(.*)$" $package_url _ package_url
+ }
+ #my log "--R package_url= $package_url (was $info(url))"
+ my package_url $package_url
+ my package_key $info(package_key)
my instance_name $info(instance_name)
- if {![my exists url]} {
+ if {[my exists url] && [info exists root]} {
+ regexp "^${root}(.*)$" $url _ url
+ } else {
+ my log "--R we have no url, use package_url"
# if we have no more information, we use the package_url as actual url
- set url [my package_url]
- }
+ set url $package_url
+ }
my set_url -url $url
}
Package instproc set_url {-url} {
my url $url
my set object [string range [my url] [string length [my package_url]] end]
+ #my log "--R object set to [my set object], [my serialize]"
}
# Package instproc destroy {} {
Index: openacs-4/packages/xotcl-core/tcl/generic-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/generic-procs.tcl,v
diff -u -N -r1.40.2.1 -r1.40.2.2
--- openacs-4/packages/xotcl-core/tcl/generic-procs.tcl 15 Jan 2007 08:49:58 -0000 1.40.2.1
+++ openacs-4/packages/xotcl-core/tcl/generic-procs.tcl 1 Aug 2007 21:39:32 -0000 1.40.2.2
@@ -53,69 +53,221 @@
}
proc package_id_from_package_key { key } {
- set id [apm_version_id_from_package_key $key]
- set mount_url [site_node::get_children -all -package_key $key -node_id $id]
- array set site_node [site_node::get -url $mount_url]
- return $site_node(package_id)
+ return [db_string dbqd.null.get_package_id_from_key \
+ {select package_id from apm_packages where package_key = :key}]
}
CrClass instproc unknown { obj args } {
my log "unknown called with $obj $args"
}
+ #
+ # The following methods are used oracle, postgres specific code (locking,
+ # for the type hierarchies, ...
+ #
+ CrClass instproc lock {tablename mode} {
+ # no locking by default
+ }
+ if {[db_driverkey ""] eq "postgresql"} {
+ #
+ # Postgres
+ #
+ CrClass instproc object_types_query {
+ {-subtypes_first:boolean false}
+ } {
+ my instvar object_type_key
+ set order_clause [expr {$subtypes_first ? "order by tree_sortkey desc":""}]
+ return "select object_type from acs_object_types where
+ tree_sortkey between '$object_type_key' and tree_right('$object_type_key')
+ $order_clause"
+ }
+ CrClass instproc init_type_hierarchy {} {
+ my instvar object_type
+ my set object_type_key [db_list [my qn get_tree_sortkey] {
+ select tree_sortkey from acs_object_types
+ where object_type = :object_type
+ }]
+ }
+ CrClass instproc type_selection {-with_subtypes:boolean} {
+ my instvar object_type_key object_type
+ if {$with_subtypes} {
+ #return "acs_object_types.tree_sortkey between '$object_type_key' and tree_right('$object_type_key')"
+ #return "ci.content_type in ('[join [my object_types] ',']')"
+ return "ci.content_type in ([my object_types_query])"
+ } else {
+ return "ci.content_type = '$object_type'"
+ #return "acs_object_types.tree_sortkey = '$object_type_key'"
+ }
+ }
+ set pg_version [db_string dbqd.null.get_version {
+ select substring(version() from 'PostgreSQL #"[0-9]+.[0-9+]#".%' for '#') }]
+ ns_log notice "--Postgres Version $pg_version"
+ if {$pg_version < 8.2} {
+ ns_log notice "--Postgres Version $pg_version older than 8.2, use locks"
+ CrClass instproc lock {tablename mode} {
+ db_dml [my qn lock_objects] "LOCK TABLE $tablename IN $mode MODE"
+ }
+ }
+ } else {
+ #
+ # Oracle
+ #
+ CrClass instproc object_types_query {
+ {-subtypes_first:boolean false}
+ } {
+ my instvar object_type
+ set order_clause [expr {$subtypes_first ? "order by LEVEL desc":""}]
+ return "select object_type from acs_object_types
+ start with object_type = '$object_type'
+ connect by prior object_type = supertype $order_clause"
+ }
+ CrClass instproc init_type_hierarchy {} {
+ my set object_type_key {}
+ }
+ CrClass instproc type_selection {-with_subtypes:boolean} {
+ my instvar object_type
+ if {$with_subtypes} {
+ return "acs_objects.object_type in ([my object_types_query])"
+ } else {
+ return "acs_objects.object_type = '$object_type'"
+ }
+ }
+ }
+
CrClass set common_query_atts {
- item_id revision_id creation_user creation_date last_modified object_type
- creation_user last_modified publish_status
+ object_type item_id revision_id
+ creation_user creation_date creation_user
+ publish_status last_modified
}
if {[apm_version_names_compare [ad_acs_version] 5.2] > -1} {
CrClass lappend common_query_atts package_id
}
CrClass set common_insert_atts {name title description mime_type nls_language text}
- CrClass instproc object_types {
- {-subtypes_first:boolean false}
- } {
- my instvar object_type_key
- set order_clause [expr {$subtypes_first ? "order by tree_sortkey desc":""}]
- return [db_list get_object_types "
- select object_type from acs_object_types where
- tree_sortkey between :object_type_key and tree_right(:object_type_key)
- $order_clause
- "]
- }
-
- CrClass instproc edit_atts {} {
+ CrClass instproc edit_atts {} {
concat [[self class] set common_insert_atts] [my sql_attribute_names]
}
CrClass instproc object_type_exists {} {
my instvar object_type
- expr {$object_type eq [db_list select_type {
+ expr {$object_type eq [db_list [my qn select_type] {
select object_type from acs_object_types where
object_type = :object_type
}]}
}
+ CrClass ad_instproc folder_type_unregister_all {
+ {-include_subtypes t}
+ } {
+ Unregister the object type from all folders on the system
+
+ @param include_subtypes Boolean value (t/f) to flag whether the
+ operation should be applied on subtypes as well
+ } {
+ my instvar object_type
+ db_foreach [my qn all_folders] {
+ select folder_id from cr_folder_type_map
+ where content_type = :object_type
+ } {
+ ::xo::db::sql::content_folder unregister_content_type \
+ -folder_id $folder_id \
+ -content_type $object_type \
+ -include_subtypes $include_subtypes
+ }
+ }
+
CrClass ad_instproc folder_type {
+ {-include_subtypes t}
-folder_id
operation
} {
register the current object type for folder_id. If folder_id
is not specified, use the instvar of the class instead.
+
+ @param include_subtypes Boolean value (t/f) to flag whether the
+ operation should be applied on subtypes as well
} {
if {$operation ne "register" && $operation ne "unregister"} {
- error "[self] operation for folder_type must be '\
- register' or 'unregister'"
+ error "[self] operation for folder_type must be 'register' or 'unregister'"
}
my instvar object_type
if {![info exists folder_id]} {
my instvar folder_id
}
- db_1row register_type "select content_folder__${operation}_content_type(\
- $folder_id,:object_type,'t')"
+ ::xo::db::sql::content_folder ${operation}_content_type \
+ -folder_id $folder_id \
+ -content_type $object_type \
+ -include_subtypes $include_subtypes
}
+ CrClass instproc create_attributes {} {
+ if {[my cr_attributes] ne ""} {
+ my instvar object_type
+ set slot [self]::slot
+ if {[info command $slot] eq ""} {
+ ::xotcl::Object create $slot
+ }
+ set o [::xo::OrderedComposite new -contains [my cr_attributes]]
+ $o destroy_on_cleanup
+
+ foreach att [$o children] {
+ $att instvar attribute_name datatype pretty_name sqltype references default
+ # provide a default pretty name for the attribute based on message keys
+ if {![info exists pretty_name]} {
+ set pretty_name "#xowiki.[namespace tail [self]]-$attribute_name#"
+ }
+
+ set column_spec [::xo::db::sql map_datatype $sqltype]
+ #my log "--SQL $attribute_name datatype=$datatype, sqltype=$sqltype, column_spec=$column_spec"
+ if {[info exists references]} {append column_spec " references $references" }
+ if {[info exists default]} {append column_spec " default '$default'" }
+ append column_spec " " \
+ [::xo::db::sql datatype_constraint $sqltype [my table_name] $attribute_name]
+
+ if {![attribute::exists_p $object_type $attribute_name]} {
+ ::xo::db::sql::content_type create_attribute \
+ -content_type $object_type \
+ -attribute_name $attribute_name \
+ -datatype $datatype \
+ -pretty_name $pretty_name \
+ -column_spec [string trim $column_spec]
+ }
+ #if {![info exists default]} {
+ # set default ""
+ #}
+ #lappend parameters [list $attribute_name $default]
+ #unset default
+ }
+ #my log "--parameter [self] parameter [list $parameters]"
+ #my parameter $parameters
+
+ # TODO the following will not be needed, when we enforce xotcl 1.5.0+
+ set parameters [list]
+ foreach att [$o children] {
+ $att instvar attribute_name datatype pretty_name sqltype default help_text spec validator
+ set slot_obj [self]::slot::$attribute_name
+ #my log "--cr ::xo::Attribute create $slot_obj"
+ ::xo::Attribute create $slot_obj
+ if {![info exists default]} {
+ set default ""
+ }
+ if {[info exists help_text]} {$slot_obj help_text $help_text}
+ if {[info exists validator]} {$slot_obj validator $validator}
+ if {[info exists spec]} {$slot_obj spec $spec}
+ $slot_obj datatype $datatype
+ $slot_obj pretty_name $pretty_name
+ $slot_obj default $default
+ $slot_obj sqltype $sqltype
+ lappend parameters [list $attribute_name $default]
+ unset default
+ }
+ if {$::xotcl::version < 1.5} {
+ my parameter [concat [my info parameter] $parameters]
+ }
+ }
+ }
+
CrClass ad_instproc create_object_type {} {
Create an oacs object_type and a table for keeping the
additional attributes.
@@ -130,29 +282,22 @@
}
db_transaction {
- db_1row create_type {
- select content_type__create_type(
- :object_type,:supertype,:pretty_name, :pretty_plural,
- :table_name, :id_column, :name_method
- )
- }
- if {[my cr_attributes] ne ""} {
- set o [::xo::OrderedComposite new -contains [my cr_attributes]]
- $o destroy_on_cleanup
- foreach att [$o children] {
- $att instvar attribute_name datatype pretty_name sqltype
- db_1row create_att {
- select content_type__create_attribute(
- :object_type,:attribute_name,:datatype,
- :pretty_name,null,null,null,:sqltype
- )
- }
- }
- }
+ ::xo::db::sql::content_type create_type \
+ -content_type $object_type \
+ -supertype $supertype \
+ -pretty_name $pretty_name \
+ -pretty_plural $pretty_plural \
+ -table_name $table_name \
+ -id_column $id_column \
+ -name_method $name_method
+
+ my create_attributes
my folder_type register
}
}
+
+
CrClass ad_instproc drop_object_type {} {
Delete the object type and remove the table for the attributes.
This method should be called when all instances are deleted. It
@@ -161,14 +306,16 @@
my instvar object_type table_name
db_transaction {
my folder_type unregister
- db_1row drop_type {
- select content_type__drop_type(:object_type,'t','t')
- }
+ ::xo::db::sql::content_type drop_type \
+ -content_type $object_type \
+ -drop_children_p t \
+ -drop_table_p t
}
}
CrClass ad_instproc require_folder {
{-parent_id -100}
+ {-content_types content_revision}
-package_id
-name
} {
@@ -201,12 +348,12 @@
error "Could not determine package id or community id"
}
}
- set folder_id [ns_cache eval xotcl_object_type_cache cid-$cid {
+ set folder_id [ns_cache eval xotcl_object_type_cache root_folder-$cid {
set folder_name "$name: $cid"
if {[info command content::item::get_id_by_name] eq ""} {
set folder_id ""
- db_0or1row get_id_by_name "select item_id as folder_id from cr_items \
+ db_0or1row [my qn get_id_by_name] "select item_id as folder_id from cr_items \
where name = :folder_name and parent_id = :parent_id"
} else {
set folder_id [content::item::get_id_by_name \
@@ -218,6 +365,15 @@
-parent_id $parent_id \
-package_id $package_id -context_id $cid]
}
+ # register all specified content types
+ foreach content_type $content_types {
+ # if a content_type ends with a *, include subtypes
+ set with_subtypes [expr {[regexp {^(.*)[*]$} $content_type _ content_type] ? "t" : "f"}]
+ ::xo::db::sql::content_folder register_content_type \
+ -folder_id $folder_id \
+ -content_type $content_type \
+ -include_subtypes $with_subtypes
+ }
return $folder_id
}]
@@ -232,32 +388,21 @@
} {
}
- CrClass instproc getFormClass {-data} {
- if {[info exists data]} {
- # new style. does not depend on form variables
- if {[$data exists item_id] && [$data set item_id] != 0 && [my exists edit_form]} {
- return [my edit_form]
- } else {
- return [my form]
- }
+ CrClass instproc getFormClass {-data:required} {
+ if {[$data exists item_id] && [$data set item_id] != 0 && [my exists edit_form]} {
+ return [my edit_form]
} else {
- set item_id [::xo::cc form_parameter item_id ""] ;# item_id should be be hardcoded
- set new_p [::xo::cc form_parameter __new_p ""]
- #my log "--F item_id '$item_id', confirmed_p new_p '$new_p' [my set item_id]"
- if {$item_id ne "" && $new_p ne "1" && [my exists edit_form]} {
- #my log "--F use edit_form [my edit_form]"
- return [my edit_form]
- } else {
- return [my form]
- }
+ return [my form]
}
}
+
CrClass instproc init {} {
my instvar object_type sql_attribute_names
if {[my info superclass] ne "::Generic::CrItem"} {
my set superclass [[my info superclass] set object_type]
}
+ my init_type_hierarchy
set sql_attribute_names [list]
set o [::xo::OrderedComposite new -contains [my cr_attributes]]
$o destroy_on_cleanup
@@ -273,11 +418,12 @@
if {![my object_type_exists]} {
my create_object_type
+ } else {
+ db_transaction {
+ my create_attributes
+ }
}
- my set object_type_key [db_list get_tree_sortkey {
- select tree_sortkey from acs_object_types
- where object_type = :object_type
- }]
+
next
}
@@ -290,7 +436,7 @@
@return item_id
} {
- if {[db_0or1row entry_exists_select "\
+ if {[db_0or1row [my qn entry_exists_select] "\
select item_id from cr_items where name = :name and parent_id = :parent_id"]} {
return $item_id
}
@@ -309,7 +455,7 @@
@return cr item object
} {
- my log "-- [self args]"
+ #my log "-- [self args]"
if {![::xotcl::Object isobject $object]} {
# if the object does not yet exist, we have to create it
my create $object
@@ -328,14 +474,19 @@
lappend atts $fq
}
if {$revision_id} {
- $object db_1row fetch_from_view_revision_id "\
+ $object db_1row [my qn fetch_from_view_revision_id] "\
select [join $atts ,], i.parent_id \
from [my set table_name]i n, cr_items i,acs_objects o \
where n.revision_id = $revision_id \
and i.item_id = n.item_id \
and o.object_id = $revision_id"
} else {
- $object db_1row fetch_from_view_item_id "\
+my log "select [join $atts ,], i.parent_id \
+ from [my set table_name]i n, cr_items i, acs_objects o \
+ where i.item_id = $item_id \
+ and n.[my id_column] = coalesce(i.live_revision, i.latest_revision) \
+ and o.object_id = i.item_id"
+ $object db_1row [my qn fetch_from_view_item_id] "\
select [join $atts ,], i.parent_id \
from [my set table_name]i n, cr_items i, acs_objects o \
where i.item_id = $item_id \
@@ -344,7 +495,8 @@
}
if {[apm_version_names_compare [ad_acs_version] 5.2] <= -1} {
- $object set package_id [db_string get_pid "select package_id from cr_folders where folder_id = [$object set parent_id]"]
+ $object set package_id [db_string [my qn get_pid] \
+ "select package_id from cr_folders where folder_id = [$object set parent_id]"]
}
#my log "--AFTER FETCH\n[$object serialize]"
@@ -365,8 +517,12 @@
@param item_id id of the item to be retrieved.
@param revision_id revision-id of the item to be retrieved.
} {
- my fetch_object -object ::[expr {$revision_id ? $revision_id : $item_id}] \
- -item_id $item_id -revision_id $revision_id
+ set object ::[expr {$revision_id ? $revision_id : $item_id}]
+ if {![my isobject $object]} {
+ my fetch_object -object $object \
+ -item_id $item_id -revision_id $revision_id
+ }
+ return $object
}
CrClass ad_instproc delete {
@@ -375,14 +531,19 @@
Delete a content item from the content repository.
@param item_id id of the item to be deleted
} {
- db_exec_plsql content_item_delete {
- select content_item__delete(:item_id)
- }
+ ::xo::db::sql::content_item del -item_id $item_id
}
+ CrClass instproc object_types {
+ {-subtypes_first:boolean false}
+ } {
+ return [db_list [my qn get_object_types] \
+ [my object_types_query -subtypes_first $subtypes_first]]
+ }
+
CrClass ad_instproc instance_select_query {
{-select_attributes ""}
- {-order_clause ""}
+ {-orderby ""}
{-where_clause ""}
{-from_clause ""}
{-with_subtypes:boolean true}
@@ -395,56 +556,60 @@
returns the SQL-query to select the CrItems of the specified object_type
@select_attributes attributes for the sql query to be retrieved, in addion
to ci.item_id acs_objects.object_type, which are always returned
- @param order_clause clause for ordering the solution set
+ @param orderby for ordering the solution set
@param where_clause clause for restricting the answer set
@param with_subtypes return subtypes as well
@param count return the query for counting the solutions
@param folder_id parent_id
@param publish_status one of 'live', 'ready' or 'production'
@return sql query
} {
- my instvar object_type_key
if {![info exists folder_id]} {my instvar folder_id}
set attributes [list ci.item_id ci.name ci.publish_status acs_objects.object_type]
foreach a $select_attributes {
if {$a eq "title"} {set a cr.title}
lappend attributes $a
}
- set type_selection [expr {$with_subtypes ?
- "acs_object_types.tree_sortkey between \
- '$object_type_key' and tree_right('$object_type_key')" :
- "acs_object_types.tree_sortkey = '$object_type_key'"}]
+ set type_selection [my type_selection -with_subtypes $with_subtypes]
+ #my log "type_selection -with_subtypes $with_subtypes returns $type_selection"
if {$count} {
set attribute_selection "count(*)"
- set order_clause "" ;# no need to order when we count
+ set orderby "" ;# no need to order when we count
set page_number "" ;# no pagination when count is used
} else {
set attribute_selection [join $attributes ,]
}
+
+ set cond [list]
+ if {$type_selection ne ""} {lappend cond $type_selection}
+ if {$where_clause ne ""} {lappend cond $where_clause}
+ if {[info exists publish_status]} {lappend cond "ci.publish_status eq '$publish_status'"}
+ lappend cond "coalesce(ci.live_revision,ci.latest_revision) = cr.revision_id
+ and ci.parent_id = $folder_id and acs_objects.object_id = cr.revision_id"
- if {$where_clause ne ""} {
- set where_clause "and $where_clause"
- }
if {$page_number ne ""} {
- set pagination "offset [expr {$page_size*($page_number-1)}] limit $page_size"
+ set limit $page_size
+ set offset [expr {$page_size*($page_number-1)}]
} else {
- set pagination ""
+ set limit ""
+ set offset ""
}
- set publish_clause \
- [expr {[info exists publish_status] ? " and ci.publish_status eq '$publish_status'" : ""}]
- return "select $attribute_selection
- from acs_object_types, acs_objects, cr_items ci, cr_revisions cr $from_clause
- where $type_selection
- and acs_object_types.object_type = ci.content_type
- and coalesce(ci.live_revision,ci.latest_revision) = cr.revision_id
- and parent_id = $folder_id and acs_objects.object_id = cr.revision_id \
- $where_clause $order_clause $publish_clause $pagination"
+
+ set sql [::xo::db::sql select \
+ -vars $attribute_selection \
+ -from "acs_objects, cr_items ci, cr_revisions cr $from_clause" \
+ -where [join $cond " and "] \
+ -orderby $orderby \
+ -limit $limit -offset $offset]
+ my log "--sql=$sql"
+ return $sql
}
CrClass ad_instproc instantiate_all {
{-select_attributes ""}
- {-order_clause ""}
+ {-orderby ""}
+ {-from_clause ""}
{-where_clause ""}
{-with_subtypes:boolean true}
{-folder_id}
@@ -469,8 +634,9 @@
-folder_id $folder_id \
-select_attributes $select_attributes \
-with_subtypes $with_subtypes \
+ -from_clause $from_clause \
-where_clause $where_clause \
- -order_clause $order_clause \
+ -orderby $orderby \
-page_size $page_size -page_number $page_number] {
set __o [$object_type create ${__result}::$item_id]
$__result add $__o
@@ -485,7 +651,10 @@
{-sql ""}
{-full_statement_name ""}
} {
- Return a set of instances of folder objects.
+ Return a set of instances of objects. It creates plain objects
+ of type ::xotcl::Object just containing the variables that
+ the sql query returns.
+
The container and contained objects are automatically
destroyed on cleanup of the connection thread
} {
@@ -497,7 +666,7 @@
while {1} {
set continue [ns_db getrow $db $selection]
if {!$continue} break
- set o [Object new]
+ set o [::xotcl::Object new]
foreach {att val} [ns_set array $selection] {$o set $att $val}
if {[$o exists object_type]} {
@@ -513,7 +682,10 @@
return $__result
}
- Class create Attribute -parameter {attribute_name datatype pretty_name {sqltype "text"}}
+ Class create Attribute -parameter {
+ attribute_name datatype pretty_name {sqltype "text"} references
+ default help_text spec validator
+ }
Class create CrItem -parameter {
package_id
@@ -522,27 +694,39 @@
{nls_language en_US}
{publish_status ready}
}
+
CrItem instproc initialize_loaded_object {} {
# dummy action, to be refined
}
- CrItem ad_proc instantiate {
+ CrItem ad_proc get_object_type {
-item_id
{-revision_id 0}
} {
- Instantiate the live revision or the specified revision of an
- CrItem.
- @return object containing the attributes of the CrItem
- } {
+ Return the object type for an item_id or revision_id.
+
+ @retun object_type typically an XOTcl class
+ } {
set object_type [ns_cache eval xotcl_object_type_cache \
[expr {$item_id ? $item_id : $revision_id}] {
if {$item_id} {
- db_1row get_class "select content_type as object_type from cr_items where item_id=$item_id"
+ db_1row [my qn get_class] "select content_type as object_type from cr_items where item_id=$item_id"
} else {
- db_1row get_class "select object_type from acs_objects where object_id=$revision_id"
+ db_1row [my qn get_class] "select object_type from acs_objects where object_id=$revision_id"
}
return $object_type
}]
+ }
+
+ CrItem ad_proc instantiate {
+ -item_id
+ {-revision_id 0}
+ } {
+ Instantiate the live revision or the specified revision of an
+ CrItem.
+ @return object containing the attributes of the CrItem
+ } {
+ set object_type [my get_object_type -item_id $item_id -revision_id $revision_id]
#if {![string match "::*" $object_type]} {set object_type ::$object_type}
return [$object_type instantiate -item_id $item_id -revision_id $revision_id]
}
@@ -553,8 +737,7 @@
} {
Delete a CrItem in the database
} {
- db_1row get_class_and_folder \
- "select content_type as object_type from cr_items where item_id = $item_id"
+ set object_type [my get_object_type -item_id $item_id]
$object_type delete -item_id $item_id
}
@@ -565,7 +748,7 @@
Lookup CR item from title and folder (parent_id)
@return item_id or 0 if not successful
} {
- if {[db_0or1row entry_exists_select "\
+ if {[db_0or1row [my qn entry_exists_select] "\
select item_id from cr_items where name = :name and parent_id = :parent_id" ]} {
#my log "-- found $item_id for $name in folder '$parent_id'"
return $item_id
@@ -574,17 +757,22 @@
return 0
}
- # provide the appropriate db_* call for the view update. Earlier
- # versions up to 5.3.0d1 used db_dml, newer versions (around july
- # 2006) have to use db_0or1row, when the patch for deadlocks and
- # duplicate items is applied...
+ if {[db_driverkey ""] eq "postgresql"} {
- apm_version_get -package_key acs-content-repository -array info
- array get info
- CrItem set insert_view_operation \
- [expr {[apm_version_names_compare $info(version_name) 5.3.0d1] < 1 ? "db_dml" : "db_0or1row"}]
- array unset info
-
+ # provide the appropriate db_* call for the view update. Earlier
+ # versions up to 5.3.0d1 used db_dml, newer versions (around july
+ # 2006) have to use db_0or1row, when the patch for deadlocks and
+ # duplicate items is applied...
+
+ apm_version_get -package_key acs-content-repository -array info
+ array get info
+ CrItem set insert_view_operation \
+ [expr {[apm_version_names_compare $info(version_name) 5.3.0d1] < 1 ? "db_dml" : "db_0or1row"}]
+ array unset info
+ } else { ;# Oracle
+ CrItem set insert_view_operation db_dml
+ }
+
# uncomment the following line, if you want to force db_0or1row for
# update operations (e.g. when using the provided patch for the
# content repository in a 5.2 installation)
@@ -593,11 +781,20 @@
CrItem instproc update_content_length {storage_type revision_id} {
if {$storage_type eq "file"} {
- db_dml update_content_length "update cr_revisions \
+ db_dml [my qn update_content_length] "update cr_revisions \
set content_length = [file size [my set import_file]] \
where revision_id = $revision_id"
}
}
+ CrItem instproc update_content {revision_id content} {
+ [my info class] instvar storage_type
+ if {$storage_type eq "file"} {
+ my log "--update_content not implemented for type file"
+ } else {
+ db_dml [my qn update_content] "update cr_revisions \
+ set content = :content where revision_id = $revision_id"
+ }
+ }
CrItem instproc current_user_id {} {
if {[my isobject ::xo::cc]} {return [::xo::cc user_id]}
@@ -632,14 +829,14 @@
my instvar import_file
set text [cr_create_content_file $item_id $revision_id $import_file]
}
- $insert_view_operation revision_add \
+ $insert_view_operation [my qn revision_add] \
"insert into [[my info class] set table_name]i ([join $__atts ,]) \
values (:[join $__atts ,:])"
my update_content_length $storage_type $revision_id
if {$live_p} {
- set publish_status [my set publish_status]
- db_0or1row make_live \
- {select content_item__set_live_revision(:revision_id, :publish_status)}
+ ::xo::db::sql::content_item set_live_revision \
+ -revision_id $revision_id \
+ -publish_status [my set publish_status]
} else {
# if we do not make the revision live, use the old revision_id,
# and let CrCache save it
@@ -650,29 +847,38 @@
}
if {[apm_version_names_compare [ad_acs_version] 5.2] > -1} {
- ns_log notice "--Version 5.2 or newer [ad_acs_version]"
- CrItem set content_item__new {
- select content_item__new(:name,$parent_id,null,null,null,\
- :creation_user,null,null,\
- 'content_item',:object_type,null,:description,:mime_type,\
- :nls_language,null,null,null,'f',:storage_type, :package_id)
+ ns_log notice "--OpenACS Version 5.2 or newer [ad_acs_version]"
+# CrItem set content_item__new_args {
+# name parent_id creation_user {item_subtype "content_item"} {content_type $object_type}
+# description mime_type nls_language {is_live f} storage_type package_id
+# }
+ CrItem set content_item__new_args {
+ -name $name -parent_id $parent_id -creation_user $creation_user \
+ -item_subtype "content_item" -content_type $object_type \
+ -description $description -mime_type $mime_type -nls_language $nls_language \
+ -is_live f -storage_type $storage_type -package_id $package_id
}
} else {
- ns_log notice "--Version 5.1 or older [ad_acs_version]"
- CrItem set content_item__new {
- select content_item__new(:name,$parent_id,null,null,null,\
- :creation_user,null,null,\
- 'content_item',:object_type,null,\
- :description,:mime_type,\
- :nls_language,null,:storage_type)
+ ns_log notice "--OpenACS Version 5.1 or older [ad_acs_version]"
+# CrItem set content_item__new_args {
+# name parent_id creation_user {item_subtype "content_item"} {content_type $object_type}
+# description mime_type nls_language {is_live f} storage_type
+# }
+ CrItem set content_item__new_args {
+ -name $name -parent_id $parent_id -creation_user $creation_user \
+ -item_subtype "content_item" -content_type $object_type \
+ -description $description -mime_type $mime_type -nls_language $nls_language \
+ -is_live f -storage_type $storage_type
}
}
CrItem ad_instproc set_live_revision {-revision_id:required {-publish_status "ready"}} {
@param revision_id
@param publish_status one of 'live', 'ready' or 'production'
} {
- db_0or1row set_live_revision {select content_item__set_live_revision(:revision_id,:publish_status)}
+ ::xo::db::sql::content_item set_live_revision \
+ -revision_id $revision_id \
+ -publish_status $publish_status
}
CrItem ad_instproc save_new {-package_id -creation_user_id {-live_p:boolean true}} {
@@ -707,29 +913,39 @@
db_transaction {
$__class instvar storage_type object_type
- $__class folder_type -folder_id $parent_id register
- db_dml lock_objects "LOCK TABLE acs_objects IN SHARE ROW EXCLUSIVE MODE"
-
- set item_id [db_string insert_item \
- [subst [[self class] set content_item__new]]]
+ #$__class folder_type -folder_id $parent_id register
+ [self class] lock acs_objects "SHARE ROW EXCLUSIVE"
set revision_id [db_nextval acs_object_id_seq]
+
+ if {$name eq ""} {
+ # we have an autonamed item, use a unique value for the name
+ set name [expr {[my exists __autoname_prefix] ?
+ "[my set __autoname_prefix]$revision_id" : $revision_id}]
+ if {$title eq ""} {
+ set title [expr {[my exists __title_prefix] ?
+ "[my set __title_prefix] ($name)" : $name}]
+ }
+ }
+ set item_id [eval ::xo::db::sql::content_item new [[self class] set content_item__new_args]]
if {$storage_type eq "file"} {
set text [cr_create_content_file $item_id $revision_id $import_file]
}
#my log "--V atts=([join $__atts ,])\nvalues=(:[join $__atts ,:])"
- $insert_view_operation revision_add \
+ $insert_view_operation [my qn revision_add] \
"insert into [$__class set table_name]i ([join $__atts ,]) \
values (:[join $__atts ,:])"
my update_content_length $storage_type $revision_id
if {$live_p} {
- set publish_status [my set publish_status]
- db_0or1row make_live \
- "select content_item__set_live_revision(:revision_id,:publish_status)"
+ ::xo::db::sql::content_item set_live_revision \
+ -revision_id $revision_id \
+ -publish_status [my set publish_status]
}
}
my set revision_id $revision_id
- my db_1row get_dates {select creation_date, last_modified \
- from acs_objects where object_id = :revision_id}
+ my db_1row [my qn get_dates] {
+ select creation_date, last_modified
+ from acs_objects where object_id = :revision_id
+ }
return $item_id
}
@@ -738,89 +954,90 @@
instance variable.
} {
# delegate deletion to the class
- [my info class] delete [my set item_id]
+ [my info class] delete -item_id [my set item_id]
}
::Generic::CrItem instproc revisions {} {
TableWidget t1 -volatile \
-columns {
Field version_number -label "" -html {align right}
- ImageField edit -label "" -src /resources/acs-subsite/Zoom16.gif \
+ ImageAnchorField edit -label "" -src /resources/acs-subsite/Zoom16.gif \
-title "View Item" -alt "view" \
-width 16 -height 16 -border 0
AnchorField diff -label ""
AnchorField author -label [_ file-storage.Author]
Field content_size -label [_ file-storage.Size] -html {align right}
Field last_modified_ansi -label [_ file-storage.Last_Modified]
Field description -label [_ file-storage.Version_Notes]
- ImageField live_revision -label [_ xotcl-core.live_revision] \
+ ImageAnchorField live_revision -label [_ xotcl-core.live_revision] \
-src /resources/acs-subsite/radio.gif \
-width 16 -height 16 -border 0 -html {align center}
ImageField_DeleteIcon version_delete -label "" -html {align center}
}
set user_id [my current_user_id]
set page_id [my set item_id]
- set live_revision_id [content::item::get_live_revision -item_id $page_id]
+ set live_revision_id [::xo::db::sql::content_item get_live_revision -item_id $page_id]
my instvar package_id
set base [$package_id url]
-
- db_foreach revisions_select \
- "select ci.name, n.revision_id as version_id,
- person__name(n.creation_user) as author,
- n.creation_user as author_id,
- to_char(n.last_modified,'YYYY-MM-DD HH24:MI:SS') as last_modified_ansi,
- n.description,
- acs_permission__permission_p(n.revision_id,:user_id,'admin') as admin_p,
- acs_permission__permission_p(n.revision_id,:user_id,'delete') as delete_p,
- r.content_length,
- content_revision__get_number(n.revision_id) as version_number
- from cr_revisionsi n, cr_items ci, cr_revisions r
- where ci.item_id = n.item_id and ci.item_id = :page_id
+ set sql [::xo::db::sql select \
+ -map_function_names true \
+ -vars "ci.name, n.revision_id as version_id,\
+ person__name(n.creation_user) as author, \
+ n.creation_user as author_id, \
+ to_char(n.last_modified,'YYYY-MM-DD HH24:MI:SS') as last_modified_ansi,\
+ n.description,\
+ acs_permission__permission_p(n.revision_id,:user_id,'admin') as admin_p,\
+ acs_permission__permission_p(n.revision_id,:user_id,'delete') as delete_p,\
+ r.content_length,\
+ content_revision__get_number(n.revision_id) as version_number " \
+ -from "cr_revisionsi n, cr_items ci, cr_revisions r" \
+ -where "ci.item_id = n.item_id and ci.item_id = :page_id
and r.revision_id = n.revision_id
and exists (select 1 from acs_object_party_privilege_map m
where m.object_id = n.revision_id
and m.party_id = :user_id
- and m.privilege = 'read')
- order by n.revision_id desc" {
-
- if {$content_length < 1024} {
- if {$content_length eq ""} {set content_length 0}
- set content_size_pretty "[lc_numeric $content_length] [_ file-storage.bytes]"
- } else {
- set content_size_pretty "[lc_numeric [format %.2f [expr {$content_length/1024.0}]]] [_ file-storage.kb]"
- }
-
- set last_modified_ansi [lc_time_system_to_conn $last_modified_ansi]
-
- if {$version_id != $live_revision_id} {
- set live_revision "Make this Revision Current"
- set live_revision_icon /resources/acs-subsite/radio.gif
- } else {
- set live_revision "Current Live Revision"
- set live_revision_icon /resources/acs-subsite/radiochecked.gif
- }
-
- set live_revision_link [export_vars -base $base \
- {{m make-live-revision} {revision_id $version_id}}]
- t1 add \
- -version_number $version_number: \
- -edit.href [export_vars -base $base {{revision_id $version_id}}] \
- -author $author \
- -content_size $content_size_pretty \
- -last_modified_ansi [lc_time_fmt $last_modified_ansi "%x %X"] \
- -description $description \
- -live_revision.src $live_revision_icon \
- -live_revision.title $live_revision \
- -live_revision.href $live_revision_link \
- -version_delete.href [export_vars -base $base \
- {{m delete-revision} {revision_id $version_id}}] \
- -version_delete.title [_ file-storage.Delete_Version]
-
- [t1 last_child] set payload(revision_id) $version_id
- }
-
+ and m.privilege = 'read')" \
+ -orderby "n.revision_id desc"]
+
+ db_foreach [my qn revisions_select] $sql {
+ if {$content_length < 1024} {
+ if {$content_length eq ""} {set content_length 0}
+ set content_size_pretty "[lc_numeric $content_length] [_ file-storage.bytes]"
+ } else {
+ set content_size_pretty "[lc_numeric [format %.2f [expr {$content_length/1024.0}]]] [_ file-storage.kb]"
+ }
+
+ set last_modified_ansi [lc_time_system_to_conn $last_modified_ansi]
+
+ if {$version_id != $live_revision_id} {
+ set live_revision "Make this Revision Current"
+ set live_revision_icon /resources/acs-subsite/radio.gif
+ } else {
+ set live_revision "Current Live Revision"
+ set live_revision_icon /resources/acs-subsite/radiochecked.gif
+ }
+
+ set live_revision_link [export_vars -base $base \
+ {{m make-live-revision} {revision_id $version_id}}]
+ t1 add \
+ -version_number $version_number: \
+ -edit.href [export_vars -base $base {{revision_id $version_id}}] \
+ -author $author \
+ -content_size $content_size_pretty \
+ -last_modified_ansi [lc_time_fmt $last_modified_ansi "%x %X"] \
+ -description $description \
+ -live_revision.src $live_revision_icon \
+ -live_revision.title $live_revision \
+ -live_revision.href $live_revision_link \
+ -version_delete.href [export_vars -base $base \
+ {{m delete-revision} {revision_id $version_id}}] \
+ -version_delete.title [_ file-storage.Delete_Version]
+
+ [t1 last_child] set payload(revision_id) $version_id
+ }
+
# providing diff links to the prevision versions. This can't be done in
# the first loop, since we have not yet the revision id of entry in the next line.
set lines [t1 children]
@@ -841,7 +1058,39 @@
return [t1 asHTML]
}
+
#
+ # Object specific privilege to be used with policies
+ #
+
+ CrItem ad_instproc privilege=creator {
+ {-login true} user_id package_id method
+ } {
+
+ Define an object specific privilege to be used in the policies.
+ Grant access to a content item for the creator (creation_user)
+ of the item, and for the package admin.
+
+ } {
+ set allowed 0
+ #my log "--checking privilege [self args]"
+ if {[my exists creation_user]} {
+ if {$user_id == 0 && $login} {
+ auth::require_login
+ } elseif {[my set creation_user] == $user_id} {
+ set allowed 1
+ } else {
+ # allow the package admin always access
+ set allowed [::xo::cc permission \
+ -object_id $package_id \
+ -party_id $user_id \
+ -privilege admin]
+ }
+ }
+ return $allowed
+ }
+
+ #
# Form template class
#
@@ -870,6 +1119,7 @@
CrCache instproc delete {-item_id} {
next
ns_cache flush xotcl_object_cache ::$item_id
+ # we should probably flush as well cached revisions
}
Class CrCache::Item
@@ -969,7 +1219,7 @@
}
Form instproc new_data {} {
my instvar data
- my log "--- new_data ---"
+ #my log "--- new_data ---"
foreach __var [my form_vars] {
$data set $__var [my var $__var]
}
@@ -978,7 +1228,7 @@
return [$data set item_id]
}
Form instproc edit_data {} {
- my log "--- edit_data ---"
+ #my log "--- edit_data --- setting form vars=[my form_vars]"
my instvar data
foreach __var [my form_vars] {
$data set $__var [my var $__var]
@@ -989,7 +1239,7 @@
set old_name [::xo::cc form_parameter __object_name ""]
set new_name [$data set name]
if {$old_name ne $new_name} {
- db_dml update_rename "update cr_items set name = :new_name \
+ db_dml [my qn update_rename] "update cr_items set name = :new_name \
where item_id = [$data set item_id]"
}
}
@@ -1014,9 +1264,10 @@
}
Form instproc new_request {} {
- my log "--- new_request ---"
+ #my log "--- new_request ---"
my request create
my instvar data
+ #my log "--VAR [my var item_id]"
foreach var [[$data info class] edit_atts] {
if {[$data exists $var]} {
my var $var [list [$data set $var]]
@@ -1025,7 +1276,7 @@
}
Form instproc edit_request {item_id} {
my instvar data
- my log "--- edit_request ---"
+ #my log "--- edit_request ---"
my request write
foreach var [[$data info class] edit_atts] {
if {[$data exists $var]} {
@@ -1035,12 +1286,15 @@
}
Form instproc on_submit {item_id} {
- # dummy proc
+ # The content of this proc is strictly speaking not necessary.
+ # However, on redirects after a submit to the same page, it
+ # ensures the setting of edit_form_page_title and context
+ my request write
}
Form instproc on_validation_error {} {
my instvar edit_form_page_title context
- my log "-- "
+ #my log "-- "
set edit_form_page_title [my edit_page_title]
set context [list $edit_form_page_title]
}
@@ -1097,14 +1351,14 @@
append new_data {
category::map_object -remove_old -object_id $item_id $category_ids
#ns_log notice "-- new data category::map_object -remove_old -object_id $item_id $category_ids"
- db_dml insert_asc_named_object \
- "insert into acs_named_objects (object_id,object_name,package_id) \
- values (:item_id, :name, :package_id)"
+ #db_dml [my qn insert_asc_named_object] \
+ # "insert into acs_named_objects (object_id,object_name,package_id) \
+ # values (:item_id, :name, :package_id)"
}
append edit_data {
- db_dml update_asc_named_object \
- "update acs_named_objects set object_name = :name, \
- package_id = :package_id where object_id = :item_id"
+ #db_dml [my qn update_asc_named_object] \
+ # "update acs_named_objects set object_name = :name, \
+ # package_id = :package_id where object_id = :item_id"
#ns_log notice "-- edit data category::map_object -remove_old -object_id $item_id $category_ids"
category::map_object -remove_old -object_id $item_id $category_ids
}
@@ -1230,7 +1484,7 @@
List ad_instproc generate {
- -order_by
+ {-orderby ""}
-template
} {
the method generate is used to actually generate the list template
@@ -1241,7 +1495,6 @@
} {
my instvar object_type with_subtypes
- set order_clause [expr {[info exists order_by] ? "order by $order_by":""}]
if {![info exists template]} {
set template [my name]
}
@@ -1268,7 +1521,7 @@
-folder_id [my folder_id] \
-select_attributes $select_attributes \
-with_subtypes $with_subtypes \
- -order_clause $order_clause] {
+ -orderby $orderby] {
set view_url [export_vars -base [my view_link] {item_id}]
set edit_url [export_vars -base [my edit_link] {item_id}]
set delete_url [export_vars -base [my delete_link] {item_id}]
Index: openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/http-client-procs.tcl 1 Aug 2007 21:39:32 -0000 1.2.2.2
@@ -0,0 +1,256 @@
+namespace eval ::xo {
+ #
+ #
+ #
+ Class create HttpRequest \
+ -parameter {
+ {host}
+ {port 80}
+ {path /}
+ {url}
+ {post_data ""}
+ {content_type text/plain}
+ {request_manager}
+ {request_header_fields {}}
+ {user_agent xohttp/0.1}
+ }
+
+ HttpRequest instproc parse_url {} {
+ my instvar url host port path
+ if {[regexp {http://([^/]*)(/.*)} $url _ host path]} {
+ set port 80
+ regexp {^([^:]+):(.*)$} $host _ host port
+ } else {
+ error "unsupported or invalid url '$url'"
+ }
+ }
+
+ HttpRequest instproc init {} {
+ my instvar S post_data host port
+ my set meta [list]
+ my set data ""
+ if {[my exists url]} {my parse_url}
+
+ if {[catch {set S [socket $host $port]} err]} {
+ my cancel "error socket $host $port: $err"
+ return
+ }
+ if {[catch {
+ set method [expr {$post_data eq "" ? "GET" : "POST"}]
+ puts $S "$method [my path] HTTP/1.0"
+ puts $S "Accept: */*"
+ puts $S "Host: $host"
+ puts $S "User-Agent: [my user_agent]"
+ foreach {tag value} [my request_header_fields] {
+ #regsub -all \[\n\r\] $value {} value
+ #set tag [string trim $tag]
+ puts $S "$tag: $value"
+ }
+ my $method
+ } err]} {
+ my cancel "error send $host $port: $err"
+ return
+ }
+ }
+
+ HttpRequest instproc GET {} {
+ my instvar S
+ puts $S ""
+ my query_done
+ }
+
+ HttpRequest instproc POST {} {
+ my instvar S post_data
+ puts $S "Content-Length: [string length $post_data]"
+ puts $S "Content-Type: [my content_type]"
+ puts $S ""
+ fconfigure $S -translation {auto binary}
+ if {[regexp {; *charset=([^ ]+)$} [my content_type] _ encoding]} {
+ fconfigure $S -encoding $encoding
+ }
+ #my log "--post data blocking=[fconfigure $S -blocking]"
+ puts -nonewline $S $post_data
+ my query_done
+ }
+
+ HttpRequest instproc query_done {} {
+ my instvar S
+ flush $S
+ my received_first_line
+ }
+ HttpRequest instproc notify {method arg} {
+ if {[my exists request_manager]} {
+ [my request_manager] $method $arg [self]
+ }
+ }
+ HttpRequest instproc cancel {reason} {
+ my log "--- $reason"
+ catch {close [my set S]}
+ my notify done $reason
+ }
+
+ HttpRequest instproc finish {} {
+ catch {close [my set S]}
+ #my log "--- [my host] [my port] [my path] has finished"
+ my notify deliver [my set data]
+ }
+ HttpRequest instproc getLine {var} {
+ my upvar $var response
+ my instvar S
+ set n [gets $S response]
+ if {[eof $S]} {
+ my log "--premature eof"
+ return -2
+ }
+ if {$n == -1} {my log "--input pending, no full line"; return -1}
+ #my log "got $response"
+ return $n
+ }
+ HttpRequest instproc received_first_line {} {
+ my instvar S statusCode
+ fconfigure $S -translation crlf
+ set n [my getLine response]
+ switch -exact -- $n {
+ -2 {my cancel premature-eof; return}
+ -1 {return}
+ }
+ if {[regexp {^HTTP/([0-9.]+) +([0-9]+) *} $response _ \
+ responseHttpVersion statusCode]} {
+ my received_first_line_done
+ } else {
+ my log "--unexpected response '$response'"
+ my cancel unexpected-response
+ }
+ }
+ HttpRequest instproc received_first_line_done {} {
+ my header
+ }
+ HttpRequest instproc header {} {
+ while {1} {
+ set n [my getLine response]
+ switch -exact -- $n {
+ -2 {my cancel premature-eof; return}
+ -1 {continue}
+ 0 {break}
+ default {
+ #my log "--header $response"
+ if {[regexp -nocase {^content-length:(.+)$} $response _ length]} {
+ my set content_length [string trim $length]
+ }
+ if {[regexp -nocase {^([^:]+): *(.+)$} $response _ key value]} {
+ my lappend meta [string tolower $key] $value
+ }
+ }
+ }
+ }
+ my received_header_done
+ }
+ HttpRequest instproc received_header_done {} {
+ fconfigure [my set S] -translation binary
+ if {[my exists content_length]} {
+ my set data [read [my set S] [my set content_length]]
+ } else {
+ my set data [read [my set S]]
+ }
+ }
+
+
+ Class AsyncHttpRequest -superclass HttpRequest -parameter {
+ {timeout 10000}
+ }
+ AsyncHttpRequest instproc init {} {
+ my set to_identifier [after [my set timeout] [self] cancel timeout]
+ next
+ }
+ AsyncHttpRequest instproc POST {} {
+ if {[my exists S]} {fconfigure [my set S] -blocking false}
+ next
+ }
+ AsyncHttpRequest instproc cancel {reason} {
+ if {$reason ne "timeout"} {
+ after cancel [my set to_identifier]
+ }
+ next
+ }
+ AsyncHttpRequest instproc finish {} {
+ after cancel [my set to_identifier]
+ next
+ }
+ AsyncHttpRequest instproc query_done {} {
+ my instvar S
+ flush $S
+ fconfigure $S -blocking false
+ fileevent $S readable [list [self] received_first_line]
+ }
+ AsyncHttpRequest instproc received_first_line_done {} {
+ fileevent [my set S] readable [list [self] header]
+ }
+ AsyncHttpRequest instproc received_header_done {} {
+ fconfigure [my set S] -translation binary
+ fileevent [my set S] readable [list [self] received_data]
+ }
+ AsyncHttpRequest instproc received_data {} {
+ my instvar S
+ if {[eof $S]} {
+ my finish
+ } else {
+ set block [read $S]
+ my append data $block
+ #my log "reveived [string length $block] bytes"
+ }
+ }
+
+ Class HttpRequestTrace
+ nsv_set HttpRequestTrace count 0
+
+ HttpRequestTrace instproc init {} {
+
+ #TODO remove me
+# my instvar host path
+# if {[my exists endpoint]} {
+# # soap specificities
+# my url [my set endpoint]
+# my post_data [my payload]
+# my content_type "text/xml"
+# if {[my action] eq ""} {
+# my headers [list SOAPAction [my set endpoint]]
+# } else {
+# my headers [list SOAPAction [my action]]
+# }
+# }
+
+ my instvar F post_data
+ my set meta [list]
+ my set requestCount [nsv_incr HttpRequestTrace count] ;# make it an instvar to find it in the log file
+ set F [open /tmp/req-[format %.4d [my set requestCount]] w]
+
+ set method [expr {$post_data eq "" ? "GET" : "POST"}]
+ puts $F "$method [my path] HTTP/1.0"
+ puts $F "Accept: */*"
+ puts $F "Host: [my host]"
+ puts $F "User-Agent: [my user_agent]"
+ foreach {tag value} [my request_header_fields] { puts $F "$tag: $value" }
+ next
+ }
+
+ HttpRequestTrace instproc POST {} {
+ my instvar F post_data
+ puts $F "Content-Length: [string length $post_data]"
+ puts $F "Content-Type: [my content_type]"
+ puts $F ""
+ fconfigure $F -translation {auto binary}
+ puts -nonewline $F $post_data
+ next
+ }
+
+ HttpRequestTrace instproc cancel {reason} {
+ catch {close [my set F]}
+ next
+ }
+ HttpRequestTrace instproc finish {} {
+ catch {close [my set F]}
+ next
+ }
+
+ #HttpRequest instmixin add HttpRequestTrace
+}
Index: openacs-4/packages/xotcl-core/tcl/policy-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/policy-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/policy-procs.tcl 1 Aug 2007 21:39:32 -0000 1.10.2.2
@@ -0,0 +1,191 @@
+ad_library {
+ XOTcl API for policies
+
+ @author Gustaf Neumann
+ @creation-date 2007-03-09
+ @cvs-id $Id: policy-procs.tcl,v 1.10.2.2 2007/08/01 21:39:32 gustafn Exp $
+}
+
+namespace eval ::xo {
+
+ Class Policy
+
+ Policy instproc defined_methods {class} {
+ set c [self]::$class
+ expr {[my isclass $c] ? [$c array names require_permission] : [list]}
+ }
+
+ Policy instproc check_privilege {{-login true} -user_id -package_id privilege object method} {
+ set allowed -1 ;# undecided
+ if {[acs_user::site_wide_admin_p -user_id $user_id]} {
+ return 1
+ }
+ switch $privilege {
+ none {return 1}
+ login {
+ if {$login} {
+ auth::require_login; return 1
+ } else {
+ return [expr {$user_id != 0}]
+ }
+ }
+ swa {
+ set allowed 0
+ #if {!$allowed} {
+ # ad_return_warning "Insufficient Permissions" \
+ # "Only side wide admins are allowed for this operation! ($object $method)"
+ # ad_script_abort
+ #}
+ }
+ default {
+ # try object specific privileges. These have the signature:
+ #
+ # instproc privilege= {{-login true} user_id package_id method}
+ #
+ if {[$object info methods privilege=$privilege] ne ""} {
+ if {![info exists package_id]} {set package_id [::xo::cc package_id]}
+ set allowed [$object privilege=$privilege -login $login $user_id $package_id $method]
+ }
+ }
+ }
+ #my log "--check_privilege {$privilege $object $method} ==> $allowed"
+ return $allowed
+ }
+
+ Policy instproc get_privilege {{-query_context "::xo::cc"} permission object method} {
+ # the privilege might by primitive (one word privilege)
+ # or it might be complex (attribute + privilege)
+ # or it might be conditional (primitive or complex) in a list of privilges
+
+ foreach p $permission {
+
+ set condition [lindex $p 0]
+ if {[llength $condition]>1} {
+ # we have a condition
+ foreach {cond value} $condition break
+ if {[$object condition=$cond $query_context $value]} {
+ return [my get_privilege [lrange $p 1 end] $object $method]
+ }
+ } else {
+ # we have no condition
+ return [list [expr {[llength $p] == 1 ? "primitive" : "complex"}] $p]
+ }
+ }
+ }
+
+ Policy instproc get_permission {{-check_classes true} object method} {
+ set permission ""
+ set o [self]::[namespace tail $object]
+ set key require_permission($method)
+ if {[my isobject $o] && [$o exists $key]} {
+ set permission [$o set $key]
+ } elseif {[my isobject $o] && [$o exists default_permission]} {
+ set permission [$o set default_permission]
+ } elseif {$check_classes} {
+ # we have no object specific policy information, check the classes
+ set c [$object info class]
+ foreach class [concat $c [$c info heritage]] {
+ set c [self]::[namespace tail $class]
+ if {![my isclass $c]} continue
+ set permission [my get_permission -check_classes false $class $method]
+ if {$permission ne ""} break
+ }
+ }
+ return $permission
+ }
+
+ Policy ad_instproc check_permissions {-user_id -package_id {-link ""} object method} {
+
+ This method checks whether the current user is allowed
+ or not to invoke a method based on the given policy.
+ This method is purely checking and does not force logins
+ or other side effects. It can be safely used for example
+ to check whether links should be shown or not.
+
+ @see enforce_permissions
+ @return 0 or 1
+
+ } {
+ if {![info exists user_id]} {set user_id [::xo::cc user_id]}
+ if {![info exists package_id]} {set package_id [::xo::cc package_id]}
+
+ set ctx ""
+ if {$link ne ""} {
+ set query [lindex [split $link ?] 1]
+ set ctx [::xo::Context new -destroy_on_cleanup -actual_query $query]
+ $ctx process_query_parameter
+ }
+
+ set permission [my get_permission $object $method]
+ #my log "--permission for o=$object, m=$method => $permission"
+ if {$permission ne ""} {
+ foreach {kind p} [my get_privilege -query_context $ctx $permission $object $method] break
+ #my log "--privilege = $p kind = $kind"
+ switch $kind {
+ primitive {return [my check_privilege -login false \
+ -package_id $package_id -user_id $user_id \
+ $p $object $method]}
+ complex {
+ foreach {attribute privilege} $p break
+ set id [$object set $attribute]
+ #my log "--p checking permission::permission_p -object_id $id -privilege $privilege"
+ return [::xo::cc permission -object_id $id -privilege $privilege -party_id $user_id]
+ }
+ }
+ }
+ return 0
+ }
+
+ Policy ad_instproc enforce_permissions {-user_id -package_id object method} {
+
+ This method checks whether the current user is allowed
+ or not to invoke a method based on the given policy and
+ forces logins if required.
+
+ @see check_permissions
+ @return 0 or 1
+
+ } {
+ if {![info exists user_id]} {set user_id [::xo::cc user_id]}
+ if {![info exists package_id]} {set package_id [::xo::cc package_id]}
+
+ #my log "--p enforce_permissions {$object $method}"
+ set allowed 0
+ set permission [my get_permission $object $method]
+ if {$permission ne ""} {
+ foreach {kind p} [my get_privilege $permission $object $method] break
+ switch $kind {
+ primitive {
+ set allowed [my check_privilege \
+ -user_id $user_id -package_id $package_id \
+ $p $object $method]
+ set privilege $p
+ }
+ complex {
+ foreach {attribute privilege} $p break
+ set id [$object set $attribute]
+ set allowed [::xo::cc permission -object_id $id \
+ -privilege $privilege \
+ -party_id $user_id]
+ }
+ }
+ }
+
+ #my log "--p enforce_permissions {$object $method} : $permission ==> $allowed"
+
+ if {!$allowed} {
+ if {$permission eq ""} {
+ ns_log notice "permission::require_permission: no permission for " \
+ "$object->$method defined"
+ } else {
+ ns_log notice "permission::require_permission: $user_id doesn't \
+ have $privilege on $object"
+ }
+ ad_return_forbidden "Permission Denied" [_ xotcl-core.policy-error-insufficient_permissions]
+ ad_script_abort
+ }
+
+ return $allowed
+ }
+
+}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/tcl/test/xotcl-avail-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/tcl/test/xotcl-avail-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xotcl-core/tcl/test/xotcl-avail-procs.tcl 1 Aug 2007 21:39:32 -0000 1.1.2.2
@@ -0,0 +1,27 @@
+ad_library {
+ Test the availability of xotcl
+}
+
+
+aa_register_case -cats {api smoke} check_xotcl {
+ Basic test of the availability of xotcl
+} {
+ proc ? {cmd expected {msg ""}} {
+ set r [uplevel $cmd]
+ if {$msg eq ""} {set msg $cmd}
+ aa_true $msg [expr {$r eq $expected}]
+ #if {$r ne $expected} {
+ # test errmsg "$msg returned '$r' ne '$expected'"
+ #} else {
+ # test okmsg "$msg - passed ([t1 diff] ms)"
+ #}
+ }
+ ? {expr {$::xotcl::version < 1.4}} 0 "XOTcl Version $::xotcl::version >= 1.4"
+ set ns_cache_version_old [catch {ns_cache names xowiki_cache xxx}]
+ if {$ns_cache_version_old} {
+ ? {set x old} new "upgrade ns_cache: cvs -z3 -d:pserver:anonymous@aolserver.cvs.sourceforge.net:/cvsroot/aolserver co nscache"
+ } else {
+ ? {set x new} new "ns_cache version seems up to date"
+ }
+
+}
\ No newline at end of file
Index: openacs-4/packages/xotcl-core/www/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xotcl-core/www/index.tcl,v
diff -u -N -r1.3.2.1 -r1.3.2.2
--- openacs-4/packages/xotcl-core/www/index.tcl 15 Jan 2007 08:49:59 -0000 1.3.2.1
+++ openacs-4/packages/xotcl-core/www/index.tcl 1 Aug 2007 21:39:32 -0000 1.3.2.2
@@ -64,7 +64,7 @@
append output "[::xotcl::api object_link {} $cl]
\n"
+ append result [my graphHTML \
+ -nodes [array get user] -edges $edges \
+ -max_edges $max_edges -cutoff $cutoff \
+ -base collab -attrib user_id]
+ }
+
+ return $result
+ }
+
+
+ Class create activity-graph \
+ -superclass ::xowiki::portlet::graph \
+ -parameter {
+ {parameter_declaration {
+ {-max_edges 70}
+ {-cutoff 0.1}
+ {-max_activities:integer 100}
+ {-show_anonymous "message"}
+ }}
+ }
+
+ activity-graph instproc render {} {
+ my get_parameters
+
+ if {$show_anonymous ne "all" && [::xo::cc user_id] eq 0} {
+ return "You must login to see the [namespace tail [self class]]"
+ }
+
+ set folder_id [$package_id folder_id]
+
+ # there must be a better way to handle temporaray tables safely....
+ catch {db_dml [my qn drop_temp_table] {drop table XOWIKI_TEMP_TABLE}}
+
+ set sql "create global temporary table XOWIKI_TEMP_TABLE on commit preserve rows as "
+ set subquery [::xo::db::sql select \
+ -vars "i.item_id, revision_id, creation_user" \
+ -from "cr_revisions cr, cr_items i, acs_objects o" \
+ -where "cr.item_id = i.item_id and i.parent_id = $folder_id \
+ and o.object_id = revision_id" \
+ -orderby "revision_id desc" \
+ -limit $max_activities]
+
+ # this is currently a rather ugly hack to get the suff quicky working in oracle.
+ # TODO: cleanup, different methods for oracle and postgres for handling temporary tables
+ if {[catch {db_dml [my qn get_n_most_recent_contributions] $sql$subquery}]} {
+ db_dml . "insert into XOWIKI_TEMP_TABLE (item_id,revision_id,creation_user) ($subquery)"
+ }
+
+ set total 0
+ db_foreach [my qn get_activities] {
+ select count(revision_id),item_id, creation_user
+ from XOWIKI_TEMP_TABLE
+ where creation_user is not null
+ group by item_id, creation_user
+ } {
+ lappend i($item_id) $creation_user $count
+ incr total $count
+ set count_var user_count($creation_user)
+ if {![info exists $count_var]} {set $count_var 0}
+ incr $count_var $count
+ set user($creation_user) "[::xo::get_user_name $creation_user] ([set $count_var])"
+ }
+
+ if {[catch {db_dml [my qn drop_temp_table] {drop table XOWIKI_TEMP_TABLE}} ]} {
+ db_dml [my qn trunc_temp_table] {truncate table XOWIKI_TEMP_TABLE }
+ }
+
+ if {[array size i] == 0} {
+ append result "No activities found
"
+ } elseif {[array size user] == 1} {
+ set user_id [lindex [array names user] 0]
+ append result "Last $total activities were done by user " \
+ "[::xo::get_user_name $user_id] ."
+ } else {
+ append result "
Collaborations in last $total activities by [array size user] Users in this wiki
"
+
+ foreach x [array names i] {
+ foreach {u1 c1} $i($x) {
+ foreach {u2 c2} $i($x) {
+ if {$u1 < $u2} {
+ set var collab($u1,$u2)
+ if {![info exists $var]} {set $var 0}
+ incr $var $c1
+ incr $var $c2
+ }
+ }
+ }
+ }
+
+ set max 0
+ foreach x [array names collab] {
+ if {$collab($x) > $max} {set max $collab($x)}
+ }
+
+ set edges [list]
+ foreach x [array names collab] {
+ lappend edges [list $x $collab($x) [expr {$collab($x)*5.0/$max}]]
+ }
+
+ append result [my graphHTML \
+ -nodes [array get user] -edges $edges \
+ -max_edges $max_edges -cutoff $cutoff \
+ -base collab -attrib user_id]
+ }
+
+ return $result
+ }
+
+ Class create timeline \
+ -superclass ::xowiki::Portlet \
+ -parameter {
+ {parameter_declaration {
+ -user_id
+ {-data timeline-data}
+ {-interval1 DAY}
+ {-interval2 MONTH}
+ }}
+ }
+
+ timeline instproc render {} {
+ my get_parameters
+
+ ::xowiki::Page requireJS "/resources/ajaxhelper/yui/yahoo/yahoo.js"
+ ::xowiki::Page requireJS "/resources/ajaxhelper/yui/event/event.js"
+ ::xowiki::Page requireJS "/resources/xowiki/timeline/api/timeline-api.js"
+
+ set stamp [clock format [clock seconds] -format "%b %d %Y %X %Z" -gmt true]
+ if {[info exists user_id]} {append data "?user_id=$user_id"}
+
+ return [subst -nocommands -nobackslashes {
+
+
+
+ }]
+ }
+
+ Class create user-timeline \
+ -superclass timeline \
+ -parameter {
+ {parameter_declaration {
+ -user_id
+ {-data timeline-data}
+ {-interval1 DAY}
+ {-interval2 MONTH}
+ }}
+ }
+
+ user-timeline instproc render {} {
+ my get_parameters
+ if {![info exists user_id]} {set user_id [::xo::cc user_id]]}
+ ::xo::cc set_parameter user_id $user_id
+ next
+ }
+
+}
+
+
+namespace eval ::xowiki::portlet {
+ #############################################################################
+ Class create form-menu \
+ -superclass ::xowiki::Portlet \
+ -parameter {
+ {__decoration none}
+ {parameter_declaration {
+ {-form_item_id:integer,required}
+ }}
+ }
+
+ form-menu instproc render {} {
+ my get_parameters
+ # todo return_url
+ my instvar __including_page
+ set base [$package_id pretty_link [$__including_page name]]
+ set new_link [$package_id make_link -link $base $__including_page create-new return_url]
+ set answer_link [$package_id make_link -link $base $__including_page list return_url]
+ set template [::Generic::CrItem instantiate -item_id $form_item_id]
+ set count [$template count_usages]
+ set links [list]
+ foreach l [list new_link answer_link] {
+ if {[set $l] ne ""} {
+ set label #xowiki.form-menu-$l#
+ if {$l eq "answer_link"} {append label " ($count) "}
+ lappend links "$label "
+ }
+ }
+ return "\n"
+ }
+
+ #############################################################################
+ Class create form-entry-menu \
+ -superclass ::xowiki::Portlet \
+ -parameter {
+ {__decoration none}
+ {parameter_declaration {
+ }}
+ }
+
+ form-entry-menu instproc render {} {
+ my get_parameters
+ my instvar __including_page
+ set form [$__including_page page_template]
+ set base [$package_id pretty_link [$form name]]
+ return "\n"
+ }
+
+ #############################################################################
+ Class create form-usages \
+ -superclass ::xowiki::Portlet \
+ -parameter {
+ {__decoration none}
+ {parameter_declaration {
+ {-form_item_id:integer}
+ {-form}
+ {-orderby "_last_modified,desc"}
+ {-all:boolean false}
+ {-field_names}
+ {-csv false}
+ }}
+ }
+
+ form-usages instproc render {} {
+ my get_parameters
+ my instvar __including_page
+
+ ::xowiki::Page requireCSS "/resources/acs-templating/lists.css"
+ set return_url [::xo::cc url]?[::xo::cc actual_query]
+
+ if {![info exists form_item_id]} {
+ set form_item_id [::xowiki::Form lookup -name $form -parent_id $folder_id]
+ if {$form_item_id == 0} {error "Cannot lookup page $form"}
+ }
+
+ set form_item [::xowiki::Form instantiate -item_id $form_item_id]
+ $form_item destroy_on_cleanup
+
+ if {![info exists field_names]} {
+ set fn [::xowiki::PageInstance get_short_spec_from_form_constraints \
+ -name @table \
+ -form_constraints [$form_item form_constraints]]
+ set field_names [split $fn ,]
+ }
+ if {$field_names eq ""} {
+ set field_names {_name _last_modified _creation_user}
+ }
+
+ set sql_atts [list instance_attributes]
+ foreach att [::xowiki::FormPage edit_atts] {set __att($att) 1}
+ set common_atts [list last_modified creation_user name]
+ foreach att $common_atts {
+ lappend sql_atts p.$att
+ set __att($att) 1
+ }
+
+ set form_constraints [$form_item form_constraints]
+ # set cr_field_spec [::xowiki::PageInstance get_short_spec_from_form_constraints \
+ # -name @cr_fields \
+ # -form_constraints $form_constraints]
+ # if some fields are hidden in the form, there might still be values (creation_user, etc)
+ # maybe filter hidden? ignore for the time being.
+ set cr_field_spec ""
+ #
+ set field_spec [::xowiki::PageInstance get_short_spec_from_form_constraints \
+ -name @fields \
+ -form_constraints $form_constraints]
+
+ foreach spec_name $field_names {
+ set short_spec [::xowiki::PageInstance get_short_spec_from_form_constraints \
+ -name $spec_name \
+ -form_constraints $form_constraints]
+
+ switch -glob -- $spec_name {
+ __* {error not_allowed}
+ _* {
+ set varname [string range $spec_name 1 end]
+ if {![info exists __att($varname)]} {
+ error "unknown attribute $spec_name"
+ }
+ set f [$form_item create_form_field \
+ -name $spec_name \
+ -slot [$form_item find_slot $varname] \
+ -spec $cr_field_spec,$short_spec]
+ lappend sql_atts p.$varname
+ }
+ default {
+ set f [$form_item create_form_field \
+ -name $spec_name \
+ -slot "" \
+ -spec $field_spec,$short_spec]
+ }
+ }
+ lappend form_fields $f
+ set __ff($spec_name) $f
+ }
+ #my msg ff=[array names __ff]
+ #$form_item show_fields $form_fields
+
+ if {[info exists __ff(_creation_user)]} {$__ff(_creation_user) label "By User"}
+
+ set cols ""
+ append cols {ImageField_EditIcon edit -label "" -html {style "padding: 2px;"}} \n
+ foreach fn $field_names {
+ append cols [list AnchorField $fn -label [$__ff($fn) label] -orderby $fn] \n
+ }
+ append cols [list ImageField_DeleteIcon delete -label "" ] \n
+
+ TableWidget t1 -volatile -columns $cols
+
+ #
+ # Sorting is done for the time being in tcl. This has the advantage
+ # that page_orders can be sorted with the special mixin and that
+ # instance attributes can be used for sorting as well.
+ #
+ foreach {att order} [split $orderby ,] break
+ if {$att eq "_page_order"} {
+ t1 mixin add ::xo::OrderedComposite::IndexCompare
+ }
+ t1 orderby -order [expr {$order eq "asc" ? "increasing" : "decreasing"}] $att
+
+ #
+ # build SQL query and iterate over the results
+ # maybe this could be slightly faster by using instantiate_objects
+ #
+ set publish_status_clause [expr {$all ? "" : " and ci.publish_status <> 'production' "}]
+ set items [::xowiki::FormPage instantiate_all \
+ -select_attributes $sql_atts \
+ -from_clause ", xowiki_form_pagex p" \
+ -with_subtypes false \
+ -where_clause " p.page_template = $form_item_id \
+ and p.xowiki_form_page_id = cr.revision_id \
+ $publish_status_clause" \
+ -folder_id [$package_id folder_id]]
+ $items destroy_on_cleanup
+
+ foreach p [$items children] {
+ $p set package_id $package_id
+
+ array set __ia [$p set instance_attributes]
+ set page_link [$package_id pretty_link [$p name]]
+
+ t1 add \
+ -delete delete \
+ -delete.href [$package_id make_link -link $page_link $p delete return_url] \
+ -edit edit \
+ -edit.href [$package_id make_link -link $page_link $p edit return_url]
+
+ set __c [t1 last_child]
+ $__c set _name.href $page_link
+ foreach __fn $field_names {
+ switch -glob -- $__fn {
+ __* {error not_allowed}
+ _* {set __value [$p set [string range $__fn 1 end]]}
+ default {
+ if {[info exists __ia($__fn)]} {
+ set __value $__ia($__fn)
+ } else {
+ # the field was added after the current entry was created
+ set __value ""
+ }
+ }
+ }
+ if {[$__ff($__fn) istype ::xowiki::FormField::richtext]} {
+ $__c set $__fn.richtext 1
+ }
+ $__c set $__fn [$__ff($__fn) pretty_value $__value]
+ }
+ }
+
+ if {$csv} {
+ return [t1 write_csv]
+ }
+
+ set base [$package_id pretty_link [$__including_page name]]
+ set label [$__including_page name]
+ append html [_ xowiki.entries_using_form [list form "$label "]]
+ append html [t1 asHTML]
+ append html "csv "
+ return $html
+ }
+}
+
\ No newline at end of file
Index: openacs-4/packages/xowiki/tcl/xowiki-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/tcl/xowiki-procs.tcl 1 Aug 2007 21:39:24 -0000 1.162.2.2
@@ -0,0 +1,1386 @@
+ad_library {
+ XoWiki - main libraray classes and objects
+
+ @creation-date 2006-01-10
+ @author Gustaf Neumann
+ @cvs-id $Id: xowiki-procs.tcl,v 1.162.2.2 2007/08/01 21:39:24 gustafn Exp $
+}
+
+namespace eval ::xowiki {
+ #
+ # create classes for different kind of pages
+ #
+ ::Generic::CrClass create Page -superclass ::Generic::CrItem \
+ -pretty_name "XoWiki Page" -pretty_plural "XoWiki Pages" \
+ -table_name "xowiki_page" -id_column "page_id" \
+ -mime_type text/html \
+ -cr_attributes {
+ if {[::xo::db::has_ltree]} {
+ ::Generic::Attribute new -attribute_name page_order -datatype text \
+ -sqltype ltree -validator page_order
+ }
+ ::Generic::Attribute new -attribute_name creator -datatype text
+ } \
+ -parameter {
+ page_id
+ {revision_id 0}
+ item_id
+ object_type
+ parent_id
+ package_id
+ name
+ title
+ text
+ description
+ nls_language
+ {folder_id -100}
+ {lang en}
+ {render_adp 1}
+ {absolute_links 0}
+ last_modified
+ creation_user
+ } \
+ -form ::xowiki::WikiForm
+
+ # TODO: the following slot definitions are not meant to stay this way.
+ # when we change to the xotcl 1.5.0+ slots, this will go away
+ if {$::xotcl::version < 1.5} {
+ if {![::xotcl::Object isobject ::xowiki::Page::slot]} {
+ ::xotcl::Object create ::xowiki::Page::slot
+ }
+ foreach parameter {name title description text nls_language publish_date creation_user last_modified} {
+ if {![::xotcl::Object isobject ::xowiki::Page::slot::$parameter]} {
+ ::xo::Attribute create ::xowiki::Page::slot::$parameter
+ }
+ }
+ }
+
+ ::xowiki::Page::slot::name set pretty_name #xowiki.Page-name#
+ ::xowiki::Page::slot::name set required true
+ ::xowiki::Page::slot::name set help_text #xowiki.Page-name-help_text#
+ ::xowiki::Page::slot::name set datatype text
+ ::xowiki::Page::slot::name set validator name
+
+ ::xowiki::Page::slot::title set pretty_name #xowiki.Page-title#
+ ::xowiki::Page::slot::title set required true
+ ::xowiki::Page::slot::title set datatype text
+
+ ::xowiki::Page::slot::description set pretty_name #xowiki.Page-description#
+ ::xowiki::Page::slot::description set spec "textarea,cols=80,rows=2"
+ ::xowiki::Page::slot::description set datatype text
+
+ ::xowiki::Page::slot::text set pretty_name #xowiki.Page-text#
+ ::xowiki::Page::slot::text set spec "richtext"
+ ::xowiki::Page::slot::text set datatype text
+
+ ::xowiki::Page::slot::nls_language set pretty_name #xowiki.Page-nls_language#
+ ::xowiki::Page::slot::nls_language set datatype text
+ ::xowiki::Page::slot::nls_language set spec {select,options=[xowiki::locales]}
+
+ ::xowiki::Page::slot::last_modified set pretty_name #xowiki.Page-last_modified#
+ ::xowiki::Page::slot::last_modified set spec date
+
+ ::xowiki::Page::slot::creation_user set spec user_id
+
+ ::Generic::CrClass create PlainPage -superclass Page \
+ -pretty_name "XoWiki Plain Page" -pretty_plural "XoWiki Plain Pages" \
+ -table_name "xowiki_plain_page" -id_column "ppage_id" \
+ -mime_type text/plain \
+ -form ::xowiki::PlainWikiForm
+
+ ::Generic::CrClass create File -superclass Page \
+ -pretty_name "XoWiki File" -pretty_plural "XoWiki Files" \
+ -table_name "xowiki_file" -id_column "file_id" \
+ -storage_type file \
+ -form ::xowiki::FileForm
+
+ ::Generic::CrClass create PodcastItem -superclass File \
+ -pretty_name "Podcast Item" -pretty_plural "Podcast Items" \
+ -table_name "xowiki_podcast_item" -id_column "podcast_item_id" \
+ -cr_attributes {
+ ::Generic::Attribute new -attribute_name pub_date -datatype date \
+ -sqltype timestamp -spec "date,format=YYYY_MM_DD_HH24_MI"
+ ::Generic::Attribute new -attribute_name duration -datatype text \
+ -help_text "#xowiki.PodcastItem-duration-help_text#"
+ ::Generic::Attribute new -attribute_name subtitle -datatype text
+ ::Generic::Attribute new -attribute_name keywords -datatype text \
+ -help_text "#xowiki.PodcastItem-keywords-help_text#"
+ } \
+ -storage_type file \
+ -form ::xowiki::PodcastForm
+
+ ::Generic::CrClass create PageTemplate -superclass Page \
+ -pretty_name "XoWiki Page Template" -pretty_plural "XoWiki Page Templates" \
+ -table_name "xowiki_page_template" -id_column "page_template_id" \
+ -cr_attributes {
+ ::Generic::Attribute new -attribute_name anon_instances -datatype boolean \
+ -sqltype boolean -default "f"
+ } \
+ -form ::xowiki::PageTemplateForm
+
+ ::Generic::CrClass create PageInstance -superclass Page \
+ -pretty_name "XoWiki Page Instance" -pretty_plural "XoWiki Page Instances" \
+ -table_name "xowiki_page_instance" -id_column "page_instance_id" \
+ -cr_attributes {
+ ::Generic::Attribute new -attribute_name page_template \
+ -datatype integer -sqltype integer -references cr_items(item_id)
+ ::Generic::Attribute new -attribute_name instance_attributes \
+ -datatype text -sqltype long_text -default ""
+ } \
+ -form ::xowiki::PageInstanceForm \
+ -edit_form ::xowiki::PageInstanceEditForm
+
+ ::Generic::CrClass create Object -superclass PlainPage \
+ -pretty_name "XoWiki Object" -pretty_plural "XoWiki Objects" \
+ -table_name "xowiki_object" -id_column "xowiki_object_id" \
+ -mime_type text/xotcl \
+ -form ::xowiki::ObjectForm
+
+ ::Generic::CrClass create Form -superclass PageTemplate \
+ -pretty_name "XoWiki Form" -pretty_plural "XoWiki Forms" \
+ -table_name "xowiki_form" -id_column "xowiki_form_id" \
+ -cr_attributes {
+ ::Generic::Attribute new -attribute_name form \
+ -datatype text -sqltype long_text -default ""
+ ::Generic::Attribute new -attribute_name form_constraints \
+ -datatype text -sqltype long_text -default "" \
+ -validator form_constraints -spec "textarea,cols=100,rows=2"
+ } \
+ -form ::xowiki::FormForm
+
+ ::Generic::CrClass create FormPage -superclass PageInstance \
+ -pretty_name "XoWiki FormPage" -pretty_plural "XoWiki FormPages" \
+ -table_name "xowiki_form_page" -id_column "xowiki_form_page_id"
+
+ #::Generic::CrClass create FormInstance -superclass PageInstance \
+ # -pretty_name "XoWiki FormInstance" -pretty_plural "XoWiki FormInstances" \
+ # -table_name "xowiki_form_instance" -id_column "xowiki_form_instance_id"
+
+ #
+ # create various extra tables, indices and views
+ #
+ ::xo::db::require table xowiki_references \
+ "reference integer references cr_items(item_id) on delete cascade,
+ link_type [::xo::db::sql map_datatype text],
+ page integer references cr_items(item_id) on delete cascade"
+ ::xo::db::require index -table xowiki_references -col reference
+
+
+ ::xo::db::require table xowiki_last_visited \
+ "page_id integer references cr_items(item_id) on delete cascade,
+ package_id integer,
+ user_id integer,
+ count integer,
+ time timestamp"
+ ::xo::db::require index -table xowiki_last_visited -col user_id,page_id -unique true
+ ::xo::db::require index -table xowiki_last_visited -col user_id,package_id
+ ::xo::db::require index -table xowiki_last_visited -col time
+
+ # Oracle has a limit of 3118 characters for keys, therefore no text as type for "tag"
+ ::xo::db::require table xowiki_tags \
+ "item_id integer references cr_items(item_id) on delete cascade,
+ package_id integer,
+ user_id integer references users(user_id),
+ tag varchar(3000),
+ time timestamp"
+ ::xo::db::require index -table xowiki_tags -col user_id,item_id
+ ::xo::db::require index -table xowiki_tags -col tag,package_id
+
+
+ if {[::xo::db::has_ltree]} {
+ ::xo::db::require index -table xowiki_page -col page_order -using gist
+ }
+
+ set sortkeys [expr {[db_driverkey ""] eq "oracle" ? "" : ", ci.tree_sortkey, ci.max_child_sortkey"}]
+ ::xo::db::require view xowiki_page_live_revision \
+ "select p.*, cr.*,ci.parent_id, ci.name, ci.locale, ci.live_revision, \
+ ci.latest_revision, ci.publish_status, ci.content_type, ci.storage_type, \
+ ci.storage_area_key $sortkeys \
+ from xowiki_page p, cr_items ci, cr_revisions cr \
+ where p.page_id = ci.live_revision \
+ and p.page_id = cr.revision_id \
+ and ci.publish_status <> 'production'"
+
+ #
+ # Page definitions
+ #
+
+
+ Page set recursion_count 0
+ Page array set RE {
+ include {([^\\]){{([^<]+?)}}(\s|<|$)?}
+ anchor {([^\\])\\\[\\\[([^\]]+?)\\\]\\\]}
+ div {()([^\\])>>([^&<]*?)<<()([ \n]*)?}
+ clean {[\\](\{\{|>>|\[\[)}
+ clean2 { *(
\n"
+ }
+ if {[info exists ::js_order]} {
+ foreach file $::js_order {
+ if {[string match "*;*" $file]} {
+ # it is not a file, but some javascipt statements
+ append result "\n"
+ } else {
+ append result "\n"
+ }
+ }
+ }
+ return $result
+ }
+ Page proc quoted_html_content text {
+ list [ad_text_to_html $text] text/html
+ }
+
+ #
+ # Operations on the whole instance
+ #
+
+ #
+ # Page marshall/demarshall
+ #
+
+
+ Page instproc marshall {} {
+ my instvar name
+ if {[regexp {^..:[0-9]+$} $name] ||
+ [regexp {^[0-9]+$} $name]} {
+ #
+ # for anonymous entries, names might clash in the target
+ # instance. If we create on the target site for anonymous
+ # entries always new instances, we end up with duplicates.
+ # Therefore, we rename anonymous entries during export to
+ # ip_address:port/item_id
+ #
+ set old_name $name
+ set server [ns_info server]
+ set port [ns_config ns/server/${server}/module/nssock port]
+ set name [ns_info address]:${port}/[my item_id]
+ set content [my serialize]
+ set name $old_name
+ } else {
+ set content [my serialize]
+ }
+ return $content
+ }
+
+ File instproc marshall {} {
+ set fn [my full_file_name]
+ set F [open $fn]
+ fconfigure $F -translation binary
+ set C [read $F]
+ close $F
+ my set __file_content [::base64::encode $C]
+ next
+ }
+
+ Page instproc demarshall {-parent_id -package_id -creation_user} {
+ # this method is the counterpart of marshall
+ my set parent_id $parent_id
+ my set package_id $package_id
+ my set creation_user $creation_user
+ #
+ # if we import from an instance without page_orders into an instance
+ # with page_orders, we need default values
+ if {[::xo::db::has_ltree] && ![my exists page_order]} {
+ my set page_order ""
+ }
+ # in the general case, no more actions required
+ }
+
+ File instproc demarshall {args} {
+ next
+ # we have to care about recoding the file content
+ my instvar import_file __file_content
+ set import_file [ns_tmpnam]
+ set F [open $import_file w]
+ fconfigure $F -translation binary
+ puts -nonewline $F [::base64::decode $__file_content]
+ close $F
+ }
+
+ # set default values.
+ # todo: with slots, it should be easier to set default values
+ # for non existing variables
+ PageInstance instproc demarshall {args} {
+ # some older versions do not have anon_instances
+ if {![my exists anon_instances]} {
+ my set anon_instances "f"
+ }
+ next
+ }
+ Form instproc demarshall {args} {
+ # some older versions do not have anon_instances
+ if {![my exists anon_instances]} {
+ my set anon_instances "t"
+ }
+ next
+ }
+
+ Page instproc copy_content_vars {-from_object:required} {
+ array set excluded_var {
+ folder_id 1 package_id 1 absolute_links 1 lang_links 1
+ publish_status 1 item_id 1 revision_id 1 last_modified 1 parent_id 1
+ }
+ foreach var [$from_object info vars] {
+ if {![info exists excluded_var($var)]} {
+ my set $var [$from_object set $var]
+ }
+ }
+ }
+
+ Page proc import {-user_id -package_id -folder_id {-replace 0} -objects} {
+ my log "DEPRECATED"
+ if {![info exists package_id]} {set package_id [::xo::cc package_id]}
+ set cmd [list $package_id import -replace $replace]
+
+ if {[info exists user_id]} {lappend cmd -user_id $user_id}
+ if {[info exists objects]} {lappend cmd -objects $objects}
+ eval $cmd
+ }
+
+ #
+ # tag management, get_tags works on instance or gobally
+ #
+
+ Page proc save_tags {-package_id:required -item_id:required -user_id:required tags} {
+ db_dml [my qn delete_tags] \
+ "delete from xowiki_tags where item_id = $item_id and user_id = $user_id"
+ foreach tag $tags {
+ db_dml [my qn insert_tag] \
+ "insert into xowiki_tags (item_id,package_id, user_id, tag, time) \
+ values ($item_id, $package_id, $user_id, :tag, current_timestamp)"
+ }
+ }
+ Page proc get_tags {-package_id:required -item_id -user_id} {
+ if {[info exists item_id]} {
+ if {[info exists user_id]} {
+ # tags for item and user
+ set tags [db_list [my qn get_tags] \
+ "SELECT distinct tag from xowiki_tags \
+ where user_id=$user_id and item_id=$item_id and package_id=$package_id"]
+ } else {
+ # all tags for this item
+ set tags [db_list [my qn get_tags] \
+ "SELECT distinct tag from xowiki_tags \
+ where item_id=$item_id and package_id=$package_id"]
+ }
+ } else {
+ if {[info exists user_id]} {
+ # all tags for this user
+ set tags [db_list [my qn get_tags] \
+ "SELECT distinct tag from xowiki_tags \
+ where user_id=$user_id and package_id=$package_id"]
+ } else {
+ # all tags for the package
+ set tags [db_list [my qn get_tags] \
+ "SELECT distinct tag from xowiki_tags \
+ where package_id=$package_id"]
+ }
+ }
+ join $tags " "
+ }
+
+
+ #
+ # Methods of ::xowiki::Page
+ #
+
+ Page instforward query_parameter {%my set package_id} %proc
+ Page instforward exists_query_parameter {%my set package_id} %proc
+ Page instforward form_parameter {%my set package_id} %proc
+ Page instforward exists_form_parameter {%my set package_id} %proc
+
+ Page instproc complete_name {name {nls_language ""}} {
+ if {![regexp {^..:} $name]} {
+ if {$name ne ""} {
+ # prepend the language prefix only, if the entry is not empty
+ if {$nls_language eq ""} {set nls_language [my set nls_language]}
+ set name [string range $nls_language 0 1]:$name
+ }
+ }
+ }
+
+# Page instproc init {} {
+# my log "--W "
+# ::xo::show_stack
+# next
+# }
+
+# Page instproc destroy {} {
+# my log "--W "
+# ::xo::show_stack
+# next
+# }
+
+ Page instproc initialize_loaded_object {} {
+ my instvar title
+ if {[info exists title] && $title eq ""} {set title [my set name]}
+ next
+ }
+
+ Page instproc regsub_eval {{-noquote:boolean false} re string cmd} {
+ if {$noquote} {
+ set map { \[ \\[ \] \\] \$ \\$ \\ \\\\}
+ } else {
+ set map { \" \\\" \[ \\[ \] \\] \$ \\$ \\ \\\\}
+ }
+# my msg "re=$re, string=$string cmd=$cmd"
+# set c [regsub -all $re [string map { \[ \\[ \] \\] \
+# \$ \\$ \\ \\\\} $string] \
+# "\[$cmd\]"]
+# my msg c=$c
+# set s [subst $c]
+# my msg s=$s
+# return $s
+ uplevel [list subst [regsub -all $re [string map $map $string] "\[$cmd\]"]]
+ }
+
+ Page instproc error_during_render {msg} {
+ return "$msg
"
+ }
+
+ Page instproc error_in_includelet {arg msg} {
+ my instvar name
+ return [my error_during_render "[_ xowiki.error_in_includelet] \n$msg"]
+ }
+
+ Page instproc include_portlet {arg} {
+ # we want to use package_id as proc-local variable, since the
+ # cross package reference might alter it locally
+ set package_id [my package_id]
+
+ # do we have a wellformed list?
+ if {[catch {set page_name [lindex $arg 0]} errMsg]} {
+ #my log "--S arg='$arg'"
+ # there is something syntactically wrong
+ return [my error_in_includelet $arg [_ xowiki.error-includelet-dash_syntax_invalid]]
+ }
+
+ # the include is either a portlet class, or a wiki page
+ if {[my isclass ::xowiki::portlet::$page_name]} {
+ # direct call, without page, not tailorable
+ set page [::xowiki::portlet::$page_name new \
+ -package_id $package_id \
+ -name $page_name \
+ -actual_query [::xo::cc actual_query]]
+ } else {
+ #
+ # Include a wiki page, tailorable.
+ #
+ # For the resolver, we create a fresh context to avoid recursive loops, when
+ # e.g. revision_id is set through a query parameter...
+ #
+ set last_context [expr {[my exists context] ? $context : "::xo::cc"}]
+
+ if {[regexp {^/(/[^?]*)[?]?(.*)$} $page_name _ url query]} {
+ #
+ # Handle cross package xowiki includes.
+ # Note, that package::initialize might change the package id.
+ #
+ ::xowiki::Package initialize -parameter {{-m view}} -url $url \
+ -actual_query $query
+ if {$package_id != 0} {
+ $package_id context [::xo::Context new -volatile]
+ set object_name [$package_id set object]
+ # A user might force the language by preceding the
+ # name with a language prefix.
+ if {![regexp {^..:} $object_name]} {
+ set object_name [my lang]:$object_name
+ }
+ set page [$package_id resolve_page $object_name __m]
+ #my msg "cross package reference $page_name ==> $page, package_id=$package_id"
+ }
+ #my log "--resolve --> $page"
+ } else {
+ $package_id context [::xo::Context new -volatile]
+ set page [$package_id resolve_page $page_name __m]
+ }
+ $package_id context $last_context
+
+ if {$page ne "" && ![$page exists __decoration]} {
+ $page set __decoration portlet
+ }
+ }
+
+ if {$page ne ""} {
+ my set __last_includelet $page
+ $page destroy_on_cleanup
+ $page set __including_page [self]
+ $page set __caller_parameters [lrange $arg 1 end]
+ #$page set __decoration portlet
+ foreach {att value} [$page set __caller_parameters] {
+ switch -- $att {
+ -decoration {$page set __decoration $value}
+ -title {$page set title $value}
+ }
+ }
+ if {[$page exists __decoration] && [$page set __decoration] ne "none"} {
+ $page mixin add ::xowiki::portlet::decoration=[$page set __decoration]
+ }
+
+ if {[catch {set html [$page render]} errorMsg]} {
+ set html [my error_during_render [_ xowiki.error-includelet-error_during_render]]
+ }
+ #my log "--include portlet returns $html"
+ return $html
+ } else {
+ return [my error_during_render [_ xowiki.error-includelet-unknown]]
+ }
+ }
+
+ Page instproc include {ch arg ch2} {
+ # make recursion depth a global variable to ease the deletion etc.
+ if {[catch {incr ::xowiki_inclusion_depth}]} {
+ set ::xowiki_inclusion_depth 1
+ }
+ if {$::xowiki_inclusion_depth > 10} {
+ return ${ch}[my error_in_includelet $arg [_ xowiki.error-includelet-nesting_to_deep]]
+ }
+ if {[regexp {^adp (.*)$} $arg _ adp]} {
+ if {[catch {lindex $adp 0} errMsg]} {
+ # there is something syntactically wrong
+ incr ::xowiki_inclusion_depth -1
+ return ${ch}[my error_in_includelet $arg [_ xowiki.error-includelet-adp_syntax_invalid]]
+ }
+ set adp [string map { " "} $adp]
+ set adp_fn [lindex $adp 0]
+ if {![string match "/*" $adp_fn]} {set adp_fn /packages/xowiki/www/$adp_fn}
+ set adp_args [lindex $adp 1]
+ if {[llength $adp_args] % 2 == 1} {
+ incr ::xowiki_inclusion_depth -1
+ set adp $adp_args
+ return ${ch}[my error_in_includelet $arg [_ xowiki.error-includelet-adp_syntax_invalid]]
+ }
+ lappend adp_args __including_page [self]
+ set including_page_level [template::adp_level]
+ if {[catch {set page [template::adp_include $adp_fn $adp_args]} errorMsg]} {
+ # in case of error, reset the adp_level to the previous value
+ set ::template::parse_level $including_page_level
+ incr ::xowiki_inclusion_depth -1
+ return ${ch}[my error_in_includelet $arg \
+ [_ xowiki.error-includelet-error_during_adp_evaluation]]
+ }
+
+ return $ch$page$ch2
+ } else {
+ # we have a direct (adp-less include)
+ # Some browsers change {{cmd -flag "..."}} into {{cmd -flag "..."}}
+ # We have to change this back
+ regsub -all {([^\\])"} $arg "\\1\"" arg
+ set html [my include_portlet $arg]
+ #my log "--include portlet returns $html"
+ incr ::xowiki_inclusion_depth -1
+ return $ch$html$ch2
+ }
+ }
+
+ Page instproc div {ch arg} {
+ if {$arg eq "content"} {
+ return "$ch"
+ } elseif {[string match left-col* $arg] \
+ || [string match right-col* $arg] \
+ || $arg eq "sidebar"} {
+ return "$ch
"
+ } elseif {$arg eq "box"} {
+ return "$ch
"
+ } elseif {$arg eq ""} {
+ return "$ch
"
+ } else {
+ return $ch
+ }
+ }
+ Page instproc anchor {ch arg} {
+ set label $arg
+ set link $arg
+ set options ""
+ regexp {^([^|]+)[|](.*)$} $arg _ link label
+ regexp {^([^|]+)[|](.*)$} $label _ label options
+ if {[string match "http*//*" $link] || [string match "//*" $link]} {
+ regsub {^//} $link / link
+ set l [ExternalLink new -label $label -href $link]
+ eval $l configure $options
+ set html [$l render]
+ $l destroy
+ return "$ch$html"
+ }
+
+ set name ""
+ my instvar parent_id package_id
+ # do we have a language link (it starts with a ':')
+ if {[regexp {^:(..):(.*)$} $link _ lang stripped_name]} {
+ set link_type language
+ } elseif {[regexp {^(file|image|swf):(.*)$} $link _ link_type stripped_name]} {
+ set lang ""
+ set name $link
+ } else {
+ # do we have a typed link?
+ if {![regexp {^([^:][^:][^:]+):((..):)?(.+)$} $link _ link_type _ lang stripped_name]} {
+ # must be an untyped link; defaults, in case the second regexp does not match either
+ set lang ""
+ set link_type link
+ set stripped_name $link
+ regexp {^(..):(.+)$} $link _ lang stripped_name
+ }
+ }
+ set normalized_name [::$package_id normalize_name $stripped_name]
+ if {$lang eq ""} {set lang [my lang]}
+ if {$name eq ""} {set name $lang:$normalized_name}
+ if {$label eq $arg} {set label $stripped_name}
+
+ Link create [self]::link \
+ -page [self] \
+ -type $link_type -name $name -lang $lang \
+ -stripped_name $normalized_name -label $label \
+ -folder_id $parent_id -package_id $package_id
+
+ if {[catch {eval [self]::link configure $options} error]} {
+ return "${ch}
Error during processing of options: $error
"
+ } else {
+ return $ch[[self]::link render]
+ }
+ }
+
+
+ Page instproc substitute_markup {source} {
+ set baseclass [expr {[[my info class] exists RE] ? [my info class] : [self class]}]
+ $baseclass instvar RE
+ #my log "-- baseclass for RE = $baseclass"
+ if {[my set mime_type] eq "text/enhanced"} {
+ set source [ad_enhanced_text_to_html $source]
+ }
+ set content ""
+ set l " "; #use one byte trailer for regexps for escaped content
+ foreach l0 [split [lindex $source 0] \n] {
+ append l $l0
+ if {[string first \{\{ $l] > -1 && [string first \}\} $l] == -1} continue
+ set l [my regsub_eval $RE(anchor) $l {my anchor "\1" "\2"}]
+ set l [my regsub_eval $RE(div) $l {my div "\2" "\3"}]
+ set l [my regsub_eval $RE(include) $l {my include "\\\1" "\2" "\3"}]
+ regsub -all $RE(clean) $l {\1} l
+ regsub -all $RE(clean2) $l { \1} l
+ append content [string range $l 1 end] \n
+ set l " "
+ }
+ #my log "--substitute_markup returns $content"
+ return $content
+ }
+
+ Page instproc adp_subst {content} {
+ #my log "--adp_subst in [my name]"
+ set __ignorelist [list RE __defaults name_method object_type_key]
+ foreach __v [my info vars] {
+ if {[info exists $__v]} continue
+ my instvar $__v
+ }
+ foreach __v [[my info class] info vars] {
+ if {[lsearch -exact $__ignorelist $__v]>-1} continue
+ if {[info exists $__v]} continue
+ [my info class] instvar $__v
+ }
+ set __ignorelist [list __v __ignorelist __varlist __template_variables__ \
+ text item_id content lang_links]
+ set __varlist [list]
+ set __template_variables__ "
\n"
+ foreach __v [lsort [info vars]] {
+ if {[lsearch -exact $__ignorelist $__v]>-1} continue
+ lappend __varlist $__v
+ append __template_variables__ "$__v: '[set $__v]'\n"
+ }
+ append __template_variables__ " \n"
+ regsub -all [template::adp_variable_regexp] $content {\1@\2;noquote@} content
+ #my log "--adp before adp_eval '[template::adp_level]'"
+ #
+ # The adp buffer has limited size. For large pages, it might happen
+ # that the buffer overflows. In Aolserver 4.5, we can increase the
+ # buffer size. In 4.0.10, we are out of luck.
+ #
+ set l [string length $content]
+ if {[catch {set bufsize [ns_adp_ctl bufsize]}]} {
+ set bufsize 0
+ }
+ if {$bufsize > 0 && $l > $bufsize} {
+ # we have aolserver 4.5, we can increase the bufsize
+ ns_adp_ctl bufsize [expr {$l + 1024}]
+ }
+ set template_code [template::adp_compile -string $content]
+ set my_parse_level [template::adp_level]
+ if {[catch {set template_value [template::adp_eval template_code]} errMsg]} {
+ set ::template::parse_level $my_parse_level
+ #my log "--adp after adp_eval '[template::adp_level]' mpl=$my_parse_level"
+ return "
Error in Page $name: $errMsg
$content
Possible values are$__template_variables__"
+ }
+ return $template_value
+ }
+
+ Page instproc get_description {content} {
+ my instvar revision_id
+ set description [my set description]
+ if {$description eq "" && $content ne ""} {
+ set description [ad_html_text_convert -from text/html -to text/plain -- $content]
+ }
+ if {$description eq "" && $revision_id > 0} {
+ set description [db_string [my qn get_description_from_syndication] \
+ "select body from syndication where object_id = $revision_id" \
+ -default ""]
+ }
+ return $description
+ }
+
+ Page instproc get_content {} {
+ #my log "--"
+ return [my substitute_markup [my set text]]
+ }
+ Page instproc set_content {text} {
+ my text [list [string map [list >> "\n >>" << "<<\n"] \
+ [string trim $text " \n"]] text/html]
+ }
+
+ Page instproc get_rich_text_spec {field_name default} {
+ my instvar package_id
+ set spec ""
+ foreach {s widget_spec} [$package_id get_parameter widget_specs] {
+ foreach {page_name var_name} [split $s ,] break
+ # in case we have no name (edit new page) we use the first value or the default.
+ set name [expr {[my exists name] ? [my set name] : $page_name}]
+ #my msg "--w T.name = '$name' var=$page_name, $var_name $field_name "
+ if {[string match $page_name $name] &&
+ [string match $var_name $field_name]} {
+ set spec $widget_spec
+ #my msg "setting spec to $spec"
+ break
+ }
+ }
+ if {$spec eq ""} {return $default}
+ return $field_name:$spec
+ }
+
+ Page instproc validate=name {name} {
+ upvar nls_language nls_language
+ my set data [self] ;# for the time being; change clobbering when validate_name becomes a method
+ set success [::xowiki::validate_name]
+ if {$success} {
+ # set the instance variable with a potentially prefixed name
+ # the classical validators do just an upvar
+ my set name $name
+ }
+ return $success
+ }
+ Page instproc validate=page_order {value} {
+ if {[my exists page_order]} {
+ set page_order [string trim $value " ."]
+ my page_order $page_order
+ }
+ return 1
+ }
+
+ Page instproc update_references {page_id references} {
+ db_dml [my qn delete_references] \
+ "delete from xowiki_references where page = $page_id"
+ foreach ref $references {
+ foreach {r link_type} $ref break
+ db_dml [my qn insert_reference] \
+ "insert into xowiki_references (reference, link_type, page) \
+ values ($r,:link_type,$page_id)"
+ }
+ }
+
+ Page proc container_already_rendered {field} {
+ if {![info exists ::xowiki_page_item_id_rendered]} {
+ return ""
+ }
+ #my log "--OMIT and not $field in ([join $::xowiki_page_item_id_rendered ,])"
+ return "and not $field in ([join $::xowiki_page_item_id_rendered ,])"
+ }
+
+ Page instproc footer {} {
+ return ""
+ }
+
+ Page instproc render {-update_references:switch} {
+ my instvar item_id revision_id references lang render_adp unresolved_references parent_id
+ my array set lang_links {found "" undefined ""}
+ #my log "-- my class=[my info class]"
+ set name [my set name]
+ regexp {^(..):(.*)$} $name _ lang name
+ set references [list]
+ set unresolved_references 0
+ #my log "--W setting unresolved_references to 0 [info exists unresolved_references]"
+ set content [my get_content]
+ #my log "--W after content [info exists unresolved_references] [my exists unresolved_references] ?? [info vars]"
+ if {$update_references || $unresolved_references > 0} {
+ my update_references $item_id [lsort -unique $references]
+ }
+ set html [expr {$render_adp ? [my adp_subst $content] : $content}]
+ if {![my exists __no_footer]} {append html [my footer]}
+ return $html
+ }
+
+ Page instproc record_last_visited {-user_id} {
+ my instvar item_id package_id
+ if {![info exists user_id]} {set user_id [ad_conn user_id]}
+ if {$user_id > 0} {
+ # only record information for authenticated users
+ db_dml [my qn update_last_visisted] \
+ "update xowiki_last_visited set time = current_timestamp, count = count + 1 \
+ where page_id = $item_id and user_id = $user_id"
+ if {[db_resultrows] < 1} {
+ db_dml [my qn insert_last_visisted] \
+ "insert into xowiki_last_visited (page_id, package_id, user_id, count, time) \
+ values ($item_id, $package_id, $user_id, 1, current_timestamp)"
+ }
+ }
+ }
+
+ #
+ # Some utility functions, called on different kind of pages
+ #
+
+ Page instproc lookup_form_field {
+ -name
+ form_fields
+ } {
+ set found 0
+ foreach f $form_fields {
+ if {[$f name] eq $name} {set found 1; break}
+ }
+ if {!$found && [regexp {^([^.]+)[.](.*)$} $name _ container component]} {
+ # components of a field
+ set f [my lookup_form_field -name $container $form_fields]::$component
+ set found 1
+ }
+ if {!$found} {
+ error "No form field with name $name found"
+ }
+ return $f
+ }
+
+ Page instproc show_fields {form_fields} {
+ # this method is for debugging only
+ set msg ""
+ foreach f $form_fields { append msg "[$f name] [$f info class], " }
+ my msg $msg
+ }
+
+
+ #
+ # Methods of ::xowiki::PlainPage
+ #
+
+ PlainPage parameter {
+ {render_adp 0}
+ }
+ PlainPage array set RE {
+ include {([^\\]){{(.+?)}}[ \n\r]}
+ anchor {([^\\])\\\[\\\[([^\]]+?)\\\]\\\]}
+ div {()([^\\])>>([^<]*?)<<}
+ clean {[\\](\{\{|>>|\[\[)}
+ clean2 {(--DUMMY NOT USED--)}
+ }
+
+ PlainPage instproc get_content {} {
+ #my log "-- my class=[my info class]"
+ return [my substitute_markup [my set text]]
+ }
+ PlainPage instproc set_content {text} {
+ my text $text
+ }
+
+ PlainPage instproc substitute_markup {source} {
+ [self class] instvar RE
+ set content ""
+ foreach l [split $source \n] {
+ set l " $l"
+ set l [my regsub_eval $RE(anchor) $l {my anchor "\1" "\2"}]
+ set l [my regsub_eval $RE(div) $l {my div "\2" "\3"}]
+ set l [my regsub_eval $RE(include) $l {my include "\1" "\2" ""}]
+ regsub -all $RE(clean) $l {\1} l
+ append content [string range $l 1 end] \n
+ }
+ return $content
+ }
+
+ #
+ # Methods of ::xowiki::File
+ #
+
+ File parameter {
+ {render_adp 0}
+ }
+ File instproc complete_name {name {fn ""}} {
+ my instvar mime_type package_id
+ switch -glob -- $mime_type {
+ image/* {set type image}
+ default {set type file}
+ }
+ if {$name ne ""} {
+ set stripped_name $name
+ regexp {^(.*):(.*)$} $name _ _t stripped_name
+ } else {
+ set stripped_name $fn
+ }
+ return ${type}:[::$package_id normalize_name $stripped_name]
+ }
+ File instproc full_file_name {} {
+ if {![my exists full_file_name]} {
+ if {[my exists item_id]} {
+ my instvar text mime_type package_id item_id revision_id
+ set storage_area_key [db_string [my qn get_storage_key] \
+ "select storage_area_key from cr_items where item_id=$item_id"]
+ my set full_file_name [cr_fs_path $storage_area_key]/$text
+ #my log "--F setting FILE=[my set full_file_name]"
+ }
+ }
+ return [my set full_file_name]
+ }
+
+ File instproc get_content {} {
+ my instvar name mime_type description parent_id package_id creation_user
+ # don't require permissions here, such that rss can present the link
+ set page_link [$package_id make_link -privilege public [self] download ""]
+ #my log "--F page_link=$page_link ---- "
+ set t [TableWidget new -volatile \
+ -columns {
+ AnchorField name -label [_ xowiki.Page-name]
+ Field mime_type -label "Content Type"
+ Field last_modified -label "Last Modified"
+ Field mod_user -label "By User"
+ Field size -label "Size"
+ }]
+
+ regsub {[.][0-9]+([^0-9])} [my set last_modified] {\1} last_modified
+ regexp {^([^:]+):(.*)$} $name _ link_type stripped_name
+ set label $stripped_name
+
+ $t add \
+ -name $stripped_name \
+ -mime_type $mime_type \
+ -name.href $page_link \
+ -last_modified $last_modified \
+ -mod_user [::xo::get_user_name $creation_user] \
+ -size [file size [my full_file_name]]
+
+ if {$link_type eq "image"} {
+ set l [Link new -volatile \
+ -page [self] \
+ -type $link_type -name $name -lang "" \
+ -stripped_name $stripped_name -label $label \
+ -folder_id $parent_id -package_id $package_id]
+ set image "
[$l render]
"
+ } else {
+ set image ""
+ }
+ return "$image
[$t asHTML]
\n
$description
"
+ }
+
+ PodcastItem instproc get_content {} {
+ set content [next]
+ append content
+ foreach i {title subtitle creator pub_date duration keywords} {
+ append content "$i: [my set $i]\n"
+ }
+ append content
+ return $content
+ }
+
+ #
+ # PageTemplate specifics
+ #
+ PageTemplate parameter {
+ {render_adp 0}
+ }
+ PageTemplate instproc count_usages {{-all false}} {
+ return [::xowiki::PageTemplate count_usages -item_id [my item_id] -all $all]
+ }
+
+ PageTemplate proc count_usages {-item_id:required {-all:boolean false}} {
+ set publish_status_clause [expr {$all ? "" : " and i.publish_status <> 'production' "}]
+ set count [db_string [my qn count_usages] \
+ "select count(page_instance_id) from xowiki_page_instance, cr_items i \
+ where page_template = $item_id \
+ $publish_status_clause \
+ and page_instance_id = coalesce(i.live_revision,i.latest_revision)"]
+ return $count
+ }
+
+ #
+ # PageInstance methods
+ #
+
+ PageInstance proc get_short_spec_from_form_constraints {-name -form_constraints} {
+ foreach name_and_spec $form_constraints {
+ foreach {spec_name short_spec} [split $name_and_spec :] break
+ if {$spec_name eq $name} {
+ #my msg "get_short_spec $name returns 1 $short_spec"
+ return $short_spec
+ }
+ }
+ return ""
+ }
+
+ PageInstance instproc get_short_spec {name} {
+ #my msg "get_short_spec $name"
+ my instvar page_template
+ # in the old-fashioned 2-form page-instance create, page_template
+ # might be non-existant or empty.
+ if {[info exists page_template] && $page_template ne "" &&
+ [$page_template exists form_constraints]} {
+ set short_spec [::xowiki::PageInstance get_short_spec_from_form_constraints \
+ -name $name -form_constraints [$page_template form_constraints]]
+ if {$short_spec ne ""} {
+ return $short_spec
+ }
+ }
+ return ""
+ }
+
+ PageInstance instproc get_field_label {name value} {
+ set short_spec [my get_short_spec $name]
+ if {$short_spec ne ""} {
+ set f [FormField new -volatile -name $name -spec $short_spec]
+ return [$f pretty_value $value]
+ }
+ return $value
+ }
+ PageInstance instproc widget_spec_from_folder_object {name given_template_name} {
+ # get the widget field specifications from the payload of the folder object
+ # for a field with a specified name in a specified page template
+ my instvar page_template
+ foreach {s widget_spec} [[my set parent_id] get_payload widget_specs] {
+ foreach {template_name var_name} [split $s ,] break
+ #ns_log notice "--w T.title = '$given_template_name' var=$name"
+ if {([string match $template_name $given_template_name] || $given_template_name eq "") &&
+ [string match $var_name $name]} {
+ return $widget_spec
+ #ns_log notice "--w using $widget for $name"
+ }
+ }
+ return ""
+ }
+ PageInstance instproc get_field_type {name default_spec} {
+ my instvar page_template
+ # get widget spec from folder (highest priority)
+ set spec [my widget_spec_from_folder_object $name [$page_template set name]]
+ if {$spec ne ""} {
+ return $spec
+ }
+ # get widget spec from attribute definition
+ set f [my create_form_field -name $name -slot [my find_slot $name]]
+ if {$f ne ""} {
+ return [$f asWidgetSpec]
+ }
+ # use default widget spec
+ return $default_spec
+ }
+
+ PageInstance instproc get_from_template {var} {
+ my instvar page_template
+ #my log "-- fetching page_template = $page_template"
+ ::Generic::CrItem instantiate -item_id $page_template
+ $page_template destroy_on_cleanup
+ return [$page_template set $var]
+ }
+
+ PageInstance instproc get_content {} {
+ set raw_template [my get_from_template text]
+ set T [my adp_subst [lindex $raw_template 0]]
+ return [my substitute_markup [list $T [lindex $raw_template 1]]]
+ }
+ PageInstance instproc template_vars {content} {
+ set result [list]
+ foreach {_ _ v} [regexp -inline -all [template::adp_variable_regexp] $content] {
+ lappend result $v ""
+ }
+ return $result
+ }
+ PageInstance instproc adp_subst {content} {
+ # initialize template variables (in case, new variables are added to template)
+ array set __ia [my template_vars $content]
+ # add extra variables as instance attributes
+ array set __ia [my set instance_attributes]
+ foreach var [array names __ia] {
+ #my log "-- set $var [list $__ia($var)]"
+ # TODO: just for the lookup, whether a field is a richt text field,
+ # there should be a more efficient and easier way...
+ if {[string match "richtext*" [my get_field_type $var text]]} {
+ # ignore the text/html info from htmlarea
+ set value [lindex $__ia($var) 0]
+ } else {
+ set value $__ia($var)
+ }
+ # the value might not be from the form attributes (e.g. title), don't clear it.
+ if {$value eq "" && [my exists $var]} continue
+ my set $var [my get_field_label $var $value]
+ }
+ next
+ }
+
+ #
+ # Methods of ::xowiki::Object
+ #
+
+ Object instproc get_content {} {
+ if {[[self]::payload info methods content] ne ""} {
+ return [my substitute_markup [[self]::payload content]]
+ } else {
+ return "
[string map {> > < <} [my set text]] "
+ }
+ }
+
+ Object instproc initialize_loaded_object {} {
+ my set_payload [my set text]
+ next
+ }
+ Object instproc set_payload {cmd} {
+ set payload [self]::payload
+ if {[my isobject $payload]} {$payload destroy}
+ ::xo::Context create $payload -requireNamespace \
+ -actual_query [::xo::cc actual_query]
+ $payload set package_id [my set package_id]
+ if {[catch {$payload contains $cmd} error ]} {
+ ns_log error "content $cmd lead to error: $error"
+ }
+ #my log "call init mixins=[my info mixin]//[$payload info mixin]"
+ $payload init
+ }
+ Object instproc get_payload {var {default ""}} {
+ set payload [self]::payload
+ if {![my isobject $payload]} {
+ ::xo::Context create $payload -requireNamespace
+ }
+ expr {[$payload exists $var] ? [$payload set $var] : $default}
+ }
+
+ #
+ # Methods of ::xowiki::Form
+ #
+ Form instproc footer {} {
+ return [my include_portlet [list form-menu -form_item_id [my item_id]]]
+ }
+
+ Form proc disable_input_fields {form} {
+ dom parse -simple -html $form doc
+ $doc documentElement root
+ set fields [$root selectNodes "//button | //input | //optgroup | //option | //select | //textarea "]
+ foreach field $fields {
+ $field setAttribute disabled "disabled"
+ }
+ return [$root asHTML]
+ }
+
+ Form instproc get_content {} {
+ my instvar text form
+ ::xowiki::Form requireFormCSS
+
+ # we assume, that the richtext is stored as 2-elem list with mime-type
+ #my log "-- text='$text'"
+ if {[lindex $text 0] ne ""} {
+ set content [my substitute_markup [my set text]]
+ } elseif {[lindex $form 0] ne ""} {
+ set content [[self class] disable_input_fields [lindex $form 0]]
+ } else {
+ set content ""
+ }
+ return $content
+ }
+
+ Form instproc list {} {
+ my view [my include_portlet [list form-usages -form_item_id [my item_id]]]
+ }
+
+
+ Form instproc validate=form_constraints {form_constraints} {
+ #
+ # First check for invalid meta characters for security reasons.
+ #
+ if {[regexp {[\[\]]} $form_constraints]} {
+ my uplevel [list set errorMsg [_ xowiki.error-form_constraint-invalid_characters]]
+ return 0
+ }
+ #
+ # Create from fields from all specs and report, if there are any errors
+ #
+ foreach name_and_spec $form_constraints {
+ foreach {spec_name short_spec} [split $name_and_spec :] break
+ if {$spec_name eq "@table" || $spec_name eq "@categories"} continue
+
+ #my msg "checking spec '$short_spec' for form field '$spec_name'"
+ if {[catch {
+ set f [my create_form_field \
+ -name $spec_name \
+ -slot [my find_slot $spec_name] \
+ -spec $short_spec]
+ $f destroy
+ } errorMsg]} {
+ my uplevel [list set errorMsg $errorMsg]
+ #my msg "ERROR: invalid spec '$short_spec' for form field '$spec_name' -- $errorMsg"
+ return 0
+ }
+ }
+ return 1
+ }
+
+
+ #
+ # Methods of ::xowiki::FormPage
+ #
+ FormPage instproc footer {} {
+ if {[my exists __no_form_page_footer]} {
+ next
+ } else {
+ return [my include_portlet [list form-entry-menu]]
+ }
+ }
+
+ FormPage instproc form_attributes {} {
+ #
+ # this method returns the form attributes (including _*)
+ #
+ my instvar page_template
+ set dont_edit [concat [[my info class] edit_atts] [list title] \
+ [::Generic::CrClass set common_query_atts]]
+
+ set template [lindex [my get_from_template text] 0]
+ #set field_names [list _name _title _description _creator _nls_language _page_order]
+ set field_names [list]
+ set form [lindex [my get_from_template form] 0]
+ if {$form eq ""} {
+ foreach {var _} [my template_vars $template] {
+ #if {[string match _* $var]} continue
+ if {[lsearch $dont_edit $var] == -1} {lappend field_names $var}
+ }
+ set form_vars 0
+ } else {
+ foreach {match 1 att} [regexp -all -inline [template::adp_variable_regexp] $form] {
+ #if {[string match _* $att]} continue
+ lappend field_names $att
+ }
+ dom parse -simple -html $form doc
+ $doc documentElement root
+ set fields [$root selectNodes "//*\[@name != ''\]"]
+ foreach field $fields {
+ set node_name [$field nodeName]
+ if {$node_name ne "input"
+ && $node_name ne "textarea"
+ && $node_name ne "select"
+ } continue
+ set att [$field getAttribute name]
+ #if {[string match _* $att]} continue
+ if {[lsearch $field_names $att] == -1} {
+ lappend field_names $att
+ }
+ }
+ set form_vars 1
+ }
+ return [list $form_vars $field_names]
+ }
+
+
+ FormPage instproc get_content {} {
+ my instvar doc root package_id page_template
+ set text [lindex [my get_from_template text] 0]
+ if {$text ne ""} {
+ #my msg "we have a template text='$text'"
+ # we have a template
+ return [next]
+ } else {
+ ::xowiki::Form requireFormCSS
+ set form [lindex [my get_from_template form] 0]
+ foreach {form_vars field_names} [my form_attributes] break
+ set form_fields [my create_form_fields $field_names]
+ set form [my regsub_eval \
+ [template::adp_variable_regexp] $form \
+ {my form_field_as_html -mode display "\\\1" "\2" $form_fields}]
+
+ dom parse -simple -html $form doc
+ $doc documentElement root
+ my set_form_data
+ return [Form disable_input_fields [$root asHTML]]
+ }
+ }
+
+ FormPage instproc get_value {before varname} {
+ #my msg "varname=$varname"
+ array set __ia [my set instance_attributes]
+ switch -glob $varname {
+ _* {set value [my set [string range $varname 1 end]]}
+ default {
+ if {[info exists __ia($varname)]} {
+ set value [set __ia($varname)]
+ } elseif {[my exists $varname]} {
+ set value [my $varname]
+ } else {
+ my msg "**** unknown variable '$varname' ****"
+ #set value **** unknown variable '$varname' ****"
+ set value ""
+ }
+ }
+ }
+
+ set f [my create_form_field -name $varname \
+ -slot [my find_slot [string trimleft $varname _]] \
+ -configuration [list -value $value]]
+ set v $value
+ set value [$f pretty_value $value]
+ #my msg "$varname [$f info class] before=$v after pretty_value=$value"
+ #my msg [$f serialize]
+
+ return $before$value
+ }
+
+ FormPage instproc adp_subst {content} {
+ set content [my regsub_eval -noquote true \
+ [template::adp_variable_regexp] " $content" {my get_value "\\\1" "\2"}]
+ #regsub -all $content {\1@\2;noquote@} content
+ return [string range $content 1 end]
+ }
+
+ FormPage instproc is_new_entry {old_name} {
+ return [expr {[my publish_status] eq "production" && $old_name eq [my revision_id]}]
+ }
+
+ FormPage instproc save_data {old_name category_ids} {
+ #my log "-- [self args]"
+ my instvar package_id name
+ db_transaction {
+ #
+ # if the newly created item was in production mode, but ordinary entries
+ # are not, change on the first save the status to ready
+ #
+ if {[my is_new_entry $old_name]} {
+ if {![$package_id get_parameter production_mode 0]} {
+ my set publish_status "ready"
+ }
+ }
+ # could be optimized, if we do not want to have categories (form constraints?)
+ category::map_object -remove_old -object_id [my item_id] $category_ids
+
+ my save
+ my log "-- old_name $old_name, name $name"
+ if {$old_name ne $name} {
+ my log "--formpage renaming"
+ db_dml [my qn update_rename] "update cr_items set name = :name \
+ where item_id = [my item_id]"
+ }
+ }
+ return [my item_id]
+ }
+
+}
+
+source [file dirname [info script]]/xowiki-www-procs.tcl
+
Index: openacs-4/packages/xowiki/tcl/xowiki-sc-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-sc-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/tcl/xowiki-sc-procs.tcl 1 Aug 2007 21:39:24 -0000 1.21.2.2
@@ -0,0 +1,144 @@
+ad_library {
+ XoWiki - Search Service Contracts
+
+ @creation-date 2006-01-10
+ @author Gustaf Neumann
+ @cvs-id $Id: xowiki-sc-procs.tcl,v 1.21.2.2 2007/08/01 21:39:24 gustafn Exp $
+}
+
+namespace eval ::xowiki {}
+
+ad_proc -private ::xowiki::datasource { revision_id } {
+ @param revision_id
+
+ returns a datasource for the search package
+} {
+ #ns_log notice "--sc datasource called with revision_id = $revision_id"
+
+ set page [::xowiki::Package instantiate_page_from_id -revision_id $revision_id -user_id 0]
+ $page volatile
+
+ #ns_log notice "--sc package=[[$page package_id] serialize]"
+ ns_log notice "--sc $page [$page set publish_status]"
+
+ if {[$page set publish_status] eq "production"} {
+ # no data source for for pages under construction
+ #ns_log notice "--sc page under construction, no datasource"
+ return [list object_id $revision_id title "" \
+ content "" keywords "" \
+ storage_type text mime text/html]
+ }
+
+ $page absolute_links 1
+ #ns_log notice "--sc setting absolute links for page = $page [$page set name]"
+
+ set html [$page render]
+ set text [ad_html_text_convert -from text/html -to text/plain -- $html]
+ #set text [ad_text_to_html $html]; #this could be used for entity encoded html text in rss entries
+
+ #::xowiki::notification::do_notifications -page $page -html $html -text $text
+
+ #ns_log notice "--sc INDEXING $revision_id -> $text"
+ #$page set unresolved_references 0
+ $page instvar item_id
+ # cleanup old stuff. This might run into an error, when search is not
+ # configured, and therefore txt does not exist. TODO: we should look for a better
+ # solution, where syndication does not depend on search....
+ catch {
+ db_dml delete_old_revisions {
+ delete from txt where object_id in \
+ (select revision_id from cr_revisions
+ where item_id = :item_id and revision_id != :revision_id)
+ }
+ }
+ foreach tag {h1 h2 h3 h4 h5 b strong} {
+ foreach {match words} [regexp -all -inline "<$tag>(\[^<\]+)$tag>" $html] {
+ foreach w [split $words] {
+ if {$w eq ""} continue
+ set word($w) 1
+ }
+ }
+ }
+ #ns_log notice "--sc keywords $revision_id -> [array names word]"
+
+ return [list object_id $revision_id title [$page title] \
+ content $text keywords [array names word] \
+ storage_type text mime text/html \
+ syndication [list \
+ link [::[$page package_id] pretty_link -absolute 1 [$page set name]] \
+ description $text \
+ author [$page set creator] \
+ category "" \
+ guid "$item_id" \
+ pubDate [$page set last_modified]] \
+ ]
+}
+
+ad_proc -private ::xowiki::url { revision_id} {
+ returns a url for a message to the search package
+} {
+ return [::xowiki::Package get_url_from_id -revision_id $revision_id]
+}
+
+
+namespace eval ::xowiki::sc {
+
+ ad_proc -private ::xowiki::sc::register_implementations {} {
+ Register the content type fts contract
+ } {
+ acs_sc::impl::new_from_spec -spec {
+ name "::xowiki::Page"
+ aliases {
+ datasource ::xowiki::datasource
+ url ::xowiki::url
+ }
+ contract_name FtsContentProvider
+ owner xowiki
+ }
+ acs_sc::impl::new_from_spec -spec {
+ name "::xowiki::PlainPage"
+ aliases {
+ datasource ::xowiki::datasource
+ url ::xowiki::url
+ }
+ contract_name FtsContentProvider
+ owner xowiki
+ }
+ acs_sc::impl::new_from_spec -spec {
+ name "::xowiki::PageInstance"
+ aliases {
+ datasource ::xowiki::datasource
+ url ::xowiki::url
+ }
+ contract_name FtsContentProvider
+ owner xowiki
+ }
+ acs_sc::impl::new_from_spec -spec {
+ name "::xowiki::FormPage"
+ aliases {
+ datasource ::xowiki::datasource
+ url ::xowiki::url
+ }
+ contract_name FtsContentProvider
+ owner xowiki
+ }
+ acs_sc::impl::new_from_spec -spec {
+ name "::xowiki::File"
+ aliases {
+ datasource ::xowiki::datasource
+ url ::xowiki::url
+ }
+ contract_name FtsContentProvider
+ owner xowiki
+ }
+}
+
+ ad_proc -private ::xowiki::sc::unregister_implementations {} {
+ acs_sc::impl::delete -contract_name FtsContentProvider -impl_name ::xowiki::Page
+ acs_sc::impl::delete -contract_name FtsContentProvider -impl_name ::xowiki::PlainPage
+ acs_sc::impl::delete -contract_name FtsContentProvider -impl_name ::xowiki::PageInstance
+ acs_sc::impl::delete -contract_name FtsContentProvider -impl_name ::xowiki::FormPage
+ acs_sc::impl::delete -contract_name FtsContentProvider -impl_name ::xowiki::File
+ }
+}
+
Index: openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/tcl/xowiki-www-procs.tcl 1 Aug 2007 21:39:25 -0000 1.95.2.2
@@ -0,0 +1,1082 @@
+ad_library {
+ XoWiki - www procs. These procs are the methods called on xowiki pages via
+ the web interface.
+
+ @creation-date 2006-04-10
+ @author Gustaf Neumann
+ @cvs-id $Id: xowiki-www-procs.tcl,v 1.95.2.2 2007/08/01 21:39:25 gustafn Exp $
+}
+
+
+namespace eval ::xowiki {
+
+ Page instproc htmlFooter {{-content ""}} {
+ my instvar package_id description
+ if {[my exists __no_footer]} {return ""}
+
+ set footer "
"
+
+ if {$description eq ""} {
+ set description [my get_description $content]
+ }
+
+ #set ::META(description) $description
+
+ if {[ns_conn isconnected]} {
+ set url "[ns_conn location][::xo::cc url]"
+ set package_url "[ns_conn location][$package_id package_url]"
+ }
+
+ if {[$package_id get_parameter "with_tags" 1] &&
+ ![my exists_query_parameter no_tags] &&
+ [::xo::cc user_id] != 0
+ } {
+ set tag_content "[my include_portlet my-tags]
"
+ set tag_includelet [my set __last_includelet]
+ set tags [$tag_includelet set tags]
+ } else {
+ set tag_content ""
+ set tags ""
+ }
+
+ if {[$package_id get_parameter "with_digg" 0] && [info exists url]} {
+ append footer "
" \
+ [my include_portlet [list digg -description $description -url $url]] "
\n"
+ }
+
+ if {[$package_id get_parameter "with_delicious" 0] && [info exists url]} {
+ append footer "
" \
+ [my include_portlet [list delicious -description $description -url $url -tags $tags]] \
+ "
\n"
+ }
+
+ if {[$package_id get_parameter "with_yahoo_publisher" 0] && [info exists package_url]} {
+ append footer "
" \
+ [my include_portlet [list my-yahoo-publisher \
+ -publisher [::xo::get_user_name [::xo::cc user_id]] \
+ -rssurl "$package_url?rss"]] \
+ "
\n"
+ }
+
+ append footer [my include_portlet my-references]
+
+ if {[$package_id get_parameter "show_per_object_categories" 1]} {
+ append footer [my include_portlet my-categories]
+ set categories_includelet [my set __last_includelet]
+ }
+
+ append footer $tag_content
+
+ if {[$package_id get_parameter "with_general_comments" 0] &&
+ ![my exists_query_parameter no_gc]} {
+ append footer [my include_portlet my-general-comments]
+ }
+
+ return "
$footer
\n"
+ }
+
+}
+
+namespace eval ::xowiki {
+
+ Page instproc view {{content ""}} {
+ # view is used only for the toplevel call, when the xowiki page is viewed
+ # this is not inteded for embedded wiki pages
+ my instvar package_id item_id
+ $package_id instvar folder_id ;# this is the root folder
+ ::xowiki::Page set recursion_count 0
+
+ set template_file [my query_parameter "template_file" \
+ [::$package_id get_parameter template_file view-default]]
+
+ if {[my isobject ::xowiki::$template_file]} {
+ $template_file before_render [self]
+ }
+
+ if {$content eq ""} {
+ set content [my render]
+ }
+ #my log "--after render"
+ set footer [my htmlFooter -content $content]
+
+ set top_portlets ""
+ set vp [$package_id get_parameter "top_portlet" ""]
+ if {$vp ne ""} {
+ set top_portlets [my include_portlet $vp]
+ }
+
+ if {[$package_id get_parameter "with_user_tracking" 1]} {
+ my record_last_visited
+ }
+
+ # Deal with the views package (many thanks to Malte for this snippet!)
+ if {[$package_id get_parameter with_views_package_if_available 1]
+ && [apm_package_installed_p "views"]} {
+ views::record_view -object_id $item_id -viewer_id [::xo::cc user_id]
+ array set views_data [views::get -object_id $item_id]
+ }
+
+ # import title, name and text into current scope
+ my instvar title name text
+
+ if {[my exists_query_parameter return_url]} {
+ set return_url [my query_parameter return_url]
+ }
+
+ if {[$package_id get_parameter "with_notifications" 1]} {
+ if {[::xo::cc user_id] != 0} { ;# notifications require login
+ set notifications_return_url [expr {[info exists return_url] ? $return_url : [ad_return_url]}]
+ set notification_type [notification::type::get_type_id -short_name xowiki_notif]
+ set notification_text "Subscribe the XoWiki instance"
+ set notification_subscribe_link \
+ [export_vars -base /notifications/request-new \
+ {{return_url $notifications_return_url}
+ {pretty_name $notification_text}
+ {type_id $notification_type}
+ {object_id $package_id}}]
+ set notification_image \
+ "
"
+ }
+ }
+ #my log "--after notifications [info exists notification_image]"
+
+ set master [$package_id get_parameter "master" 1]
+ #if {[my exists_query_parameter "edit_return_url"]} {
+ # set return_url [my query_parameter "edit_return_url"]
+ #}
+ my log "--after options"
+
+ if {$master} {
+ set context [list $title]
+ set autoname [$package_id get_parameter autoname 0]
+ set object_type [$package_id get_parameter object_type [my info class]]
+ set rev_link [$package_id make_link [self] revisions]
+ set edit_link [$package_id make_link [self] edit return_url]
+ set delete_link [$package_id make_link [self] delete return_url]
+ if {[my istype ::xowiki::FormPage]} {
+ set template_id [my page_template]
+ set form [$package_id pretty_link [$template_id name]]
+ set new_link [$package_id make_link -link $form $template_id create-new return_url]
+ } else {
+ set new_link [$package_id make_link $package_id edit-new object_type return_url autoname]
+ }
+ set admin_link [$package_id make_link -privilege admin -link admin/ $package_id {} {}]
+ set index_link [$package_id make_link -privilege public -link "" $package_id {} {}]
+ set create_in_req_locale_link ""
+
+ if {[$package_id get_parameter use_connection_locale 0]} {
+ $package_id get_name_and_lang_from_path \
+ [$package_id set object] req_lang req_local_name
+ set default_lang [$package_id default_language]
+ if {$req_lang ne $default_lang} {
+ set l [Link create new -destroy_on_cleanup \
+ -page [self] -type language -stripped_name $req_local_name \
+ -name ${default_lang}:$req_local_name -lang $default_lang \
+ -label $req_local_name -folder_id $folder_id \
+ -package_id $package_id -init \
+ -return_only undefined]
+ $l render
+ }
+ }
+
+ #my log "--after context delete_link=$delete_link "
+ set template [$folder_id get_payload template]
+ set page [self]
+
+ if {$template ne ""} {
+ set __including_page $page
+ set __adp_stub [acs_root_dir]/packages/xowiki/www/view-default
+ set template_code [template::adp_compile -string $template]
+ if {[catch {set content [template::adp_eval template_code]} errmsg]} {
+ ns_return 200 text/html "Error in Page $name: $errmsg
$template"
+ } else {
+ ns_return 200 text/html $content
+ }
+ } else {
+
+ # use adp file
+ foreach css [$package_id get_parameter extra_css ""] {::xowiki::Page requireCSS $css}
+ # refetch it, since it might have been changed via set-parameter
+ set template_file [my query_parameter "template_file" \
+ [::$package_id get_parameter template_file view-default]]
+
+ if {![regexp {^[./]} $template_file]} {
+ set template_file /packages/xowiki/www/$template_file
+ }
+ set header_stuff [::xowiki::Page header_stuff]
+ $package_id return_page -adp $template_file -variables {
+ name title item_id context header_stuff return_url
+ content footer package_id
+ rev_link edit_link delete_link new_link admin_link index_link
+ notification_subscribe_link notification_image
+ top_portlets page
+ views_data
+ }
+ }
+ } else {
+ ns_return 200 [::xo::cc get_parameter content-type text/html] $content
+ }
+ }
+}
+
+
+namespace eval ::xowiki {
+
+ Page instproc edit {
+ {-new:boolean false}
+ {-autoname:boolean false}
+ {-validaton_errors ""}
+ } {
+ my instvar package_id item_id revision_id
+ $package_id instvar folder_id ;# this is the root folder
+
+ # set some default values if they are provided
+ foreach key {name title page_order last_page_id} {
+ if {[$package_id exists_query_parameter $key]} {
+ my set $key [$package_id query_parameter $key]
+ }
+ }
+ if {$new} {
+ my set creator [::xo::get_user_name [::xo::cc user_id]]
+ my set nls_language [ad_conn locale]
+ }
+
+ set object_type [my info class]
+ if {!$new && $object_type eq "::xowiki::Object" && [my set name] eq "::$folder_id"} {
+ # if we edit the folder object, we have to do some extra magic here,
+ # since the folder object has slightly different naming conventions.
+ # ns_log notice "--editing folder object ::$folder_id, FLUSH $page"
+ ns_cache flush xotcl_object_cache [self]
+ ns_cache flush xotcl_object_cache ::$folder_id
+ my move ::$folder_id
+ set page ::$folder_id
+ #ns_log notice "--move page=$page"
+ }
+
+ #
+ # setting up folder id for file selector (use community folder if available)
+ #
+ set fs_folder_id ""
+ if {[info commands ::dotlrn_fs::get_community_shared_folder] ne ""} {
+ set fs_folder_id [::dotlrn_fs::get_community_shared_folder \
+ -community_id [::dotlrn_community::get_community_id]]
+ }
+
+ # the following line is like [$package_id url], but works as well with renamed objects
+ # set myurl [$package_id pretty_link [my form_parameter name]]
+
+ if {[my exists_query_parameter "return_url"]} {
+ set submit_link [my query_parameter "return_url" "."]
+ set return_url $submit_link
+ } else {
+ set submit_link "."
+ }
+ #my log "--u submit_link=$submit_link qp=[my query_parameter return_url]"
+
+ # we have to do template mangling here; ad_form_template writes form
+ # variables into the actual parselevel, so we have to be in our
+ # own level in order to access an pass these
+ variable ::template::parse_level
+ lappend parse_level [info level]
+ set action_vars [expr {$new ? "{edit-new 1} object_type return_url" : "{m edit} return_url"}]
+ #my log "--formclass=[$object_type getFormClass -data [self]] ot=$object_type"
+ [$object_type getFormClass -data [self]] create ::xowiki::f1 -volatile \
+ -action [export_vars -base [$package_id url] $action_vars] \
+ -data [self] \
+ -folderspec [expr {$fs_folder_id ne "" ?"folder_id $fs_folder_id":""}] \
+ -submit_link $submit_link \
+ -autoname $autoname
+
+ if {[info exists return_url]} {
+ ::xowiki::f1 generate -export [list [list return_url $return_url]]
+ } else {
+ ::xowiki::f1 generate
+ }
+
+ ::xowiki::f1 instvar edit_form_page_title context formTemplate
+
+ if {[info exists item_id]} {
+ set rev_link [$package_id make_link [self] revisions]
+ set view_link [$package_id make_link [self] view]
+ }
+ if {[info exists last_page_id]} {
+ set back_link [$package_id url]
+ }
+
+ set index_link [$package_id make_link -privilege public -link "" $package_id {} {}]
+ set html [$package_id return_page -adp /packages/xowiki/www/edit \
+ -form f1 \
+ -variables {item_id edit_form_page_title context formTemplate
+ view_link back_link rev_link index_link}]
+ template::util::lpop parse_level
+ #my log "--e html length [string length $html]"
+ return $html
+ }
+
+ Page instproc find_slot {-start_class name} {
+ if {![info exists start_class]} {
+ set start_class [my info class]
+ }
+ foreach cl [concat $start_class [$start_class info heritage]] {
+ set slotobj ${cl}::slot::$name
+ if {[my isobject $slotobj]} {
+ #my msg $slotobj
+ return $slotobj
+ }
+ }
+ return ""
+ }
+
+ Page instproc create_form_field {
+ -name
+ {-slot ""}
+ {-spec ""}
+ {-configuration ""}
+ } {
+ if {$slot eq ""} {
+ # We have no slot, so create a minimal slot. This should only happen for instance attributes
+ set slot [::xo::Attribute new -pretty_name $name -datatype text -volatile -noinit]
+ }
+
+ set spec_list [list]
+ if {[$slot exists spec]} {lappend spec_list [$slot set spec]}
+ if {$spec ne ""} {lappend spec_list $spec}
+ #my msg "[self args] spec_list $spec_list"
+ #my msg "$name, spec_list = '[join $spec_list ,]'"
+
+ if {[$slot exists pretty_name]} {
+ set label [$slot set pretty_name]
+ } else {
+ set label $name
+ my log "no pretty_name for variable $name in slot $slot"
+ }
+
+ if {[$slot exists default]} {
+ #my msg "setting ff $name default = [$slot default]"
+ set default [$slot default]
+ } else {
+ set default ""
+ }
+ set f [FormField new -name $name \
+ -id [::xowiki::Portlet html_id F.[my name].$name] \
+ -locale [my nls_language] \
+ -label $label \
+ -type [expr {[$slot exists datatype] ? [$slot set datatype] : "text"}] \
+ -help_text [expr {[$slot exists help_text] ? [$slot set help_text] : ""}] \
+ -validator [expr {[$slot exists validator] ? [$slot set validator] : ""}] \
+ -required [expr {[$slot exists required] ? [$slot set required] : "false"}] \
+ -default $default \
+ -spec [join $spec_list ,] \
+ -object [self] \
+ ]
+
+ $f destroy_on_cleanup
+ eval $f configure $configuration
+ return $f
+ }
+
+ PageInstance instproc create_form_field {
+ -name
+ {-slot ""}
+ {-spec ""}
+ {-configuration ""}
+ } {
+ set short_spec [my get_short_spec $name]
+ #my msg "create form field '$name', short_spec = '$short_spec', slot=$slot"
+ set spec_list [list]
+ if {$spec ne ""} {lappend spec_list $spec}
+ if {$short_spec ne ""} {lappend spec_list $short_spec}
+ #my msg "$name: short_spec '$short_spec', spec_list 1 = '[join $spec_list ,]'"
+ set f [next -name $name -slot $slot -spec [join $spec_list ,] -configuration $configuration]
+ return $f
+ }
+
+}
+
+namespace eval ::xowiki {
+
+ FormPage instproc create_category_fields {} {
+ set category_spec [my get_short_spec @categories]
+ foreach f [split $category_spec ,] {
+ if {$f eq "off"} {return [list]}
+ }
+
+ set category_fields [list]
+ set container_object_id [my package_id]
+ set category_trees [category_tree::get_mapped_trees $container_object_id]
+ set category_ids [category::get_mapped_categories [my item_id]]
+ #my msg "mapped category ids=$category_ids"
+
+ foreach category_tree $category_trees {
+ foreach {tree_id tree_name subtree_id assign_single_p require_category_p} $category_tree break
+
+ set options [list]
+ #if {!$require_category_p} {lappend options [list "--" ""]}
+ set value [list]
+ foreach category [category_tree::get_tree -subtree_id $subtree_id $tree_id] {
+ foreach {category_id category_name deprecated_p level} $category break
+ if {[lsearch $category_ids $category_id] > -1} {lappend value $category_id}
+ set category_name [ad_quotehtml [lang::util::localize $category_name]]
+ if { $level>1 } {
+ set category_name "[string repeat { } [expr {2*$level -4}]]..$category_name"
+ }
+ lappend options [list $category_name $category_id]
+ }
+ set f [FormField new \
+ -name "__category_${tree_name}_$tree_id" \
+ -locale [my nls_language] \
+ -label $tree_name \
+ -type select \
+ -value $value \
+ -required $require_category_p]
+ #my msg "category field [my name] created, value '$value'"
+ $f destroy_on_cleanup
+ $f options $options
+ $f multiple [expr {!$assign_single_p}]
+ lappend category_fields $f
+ }
+ return $category_fields
+ }
+
+ FormPage instproc set_form_value {att value} {
+ my instvar root item_id
+ set fields [$root selectNodes "//*\[@name='$att'\]"]
+ #my msg "found field = $fields xp=//*\[@name='$att'\]"
+ foreach field $fields {
+ # TODO missing: textarea
+ if {[$field nodeName] ne "input"} continue
+ set type [expr {[$field hasAttribute type] ? [$field getAttribute type] : "text"}]
+ # the switch should be really different objects ad classes...., but thats HTML, anyhow.
+ switch $type {
+ checkbox {$field setAttribute checked true}
+ radio {
+ set inputvalue [$field getAttribute value]
+ if {$inputvalue eq $value} {
+ $field setAttribute checked true
+ }
+ }
+ hidden -
+ text { $field setAttribute value $value}
+ default {my msg "can't handle $type so far $att=$value"}
+ }
+ }
+ }
+}
+
+
+namespace eval ::xowiki {
+
+ FormPage ad_instproc set_form_data {} {
+ Store the instance attributes in the form.
+ } {
+ #my msg "set_form_value instance attributes = [my instance_attributes]"
+ foreach {att value} [my instance_attributes] {
+ #my msg "set_form_value $att '$value'"
+ my set_form_value $att $value
+ }
+ }
+}
+
+
+namespace eval ::xowiki {
+
+ FormPage ad_instproc get_form_data {form_fields} {
+ Get the values from the form and store it as
+ instance attributes.
+ } {
+ set validation_errors 0
+ set category_ids [list]
+ array set containers [list]
+ array set __ia [my set instance_attributes]
+
+ # we have a form and get all form variables
+
+ foreach att [::xo::cc array names form_parameter] {
+ #my msg "getting att=$att"
+ switch -glob -- $att {
+ __category_* {
+ set f [my lookup_form_field -name $att $form_fields]
+ set value [$f value [::xo::cc form_parameter $att]]
+ foreach v $value {lappend category_ids $v}
+ }
+ __* {
+ # other internal variables (like __object_name) are ignored
+ }
+ _* {
+ # instance attribute fields
+ set f [my lookup_form_field -name $att $form_fields]
+ set value [$f value [::xo::cc form_parameter $att]]
+ set varname [string range $att 1 end]
+ if {![string match *.* $att]} {my set $varname $value}
+ }
+ default {
+ # user form content fields
+ set f [my lookup_form_field -name $att $form_fields]
+ set value [$f value [::xo::cc form_parameter $att]]
+ # my msg "value of $att is $value"
+ if {![string match *.* $att]} {set __ia($att) $value}
+ }
+ }
+ if {[string match *.* $att]} {
+ foreach {container component} [split $att .] break
+ lappend containers($container) $component
+ }
+ }
+
+ #
+ # In a second iteration, combine the values from the components
+ # of a container to the value of the container.
+ #
+ foreach c [array names containers] {
+ switch -glob -- $c {
+ __* {}
+ _* {
+ set f [my lookup_form_field -name $c $form_fields]
+ my set [string range $c 1 end] [$f get_compound_value]
+ }
+ default {
+ set f [my lookup_form_field -name $c $form_fields]
+ set __ia($c) [$f get_compound_value]
+ }
+ }
+ }
+
+ #
+ # Run validators
+ #
+ foreach f $form_fields {
+ set validation_error [$f validate [self]]
+ #my msg "validation of [$f name] with value '[$f value]' returns $validation_error"
+ if {$validation_error ne ""} {
+ $f error_msg $validation_error
+ incr validation_errors
+ }
+ }
+ #my log "--set instance attributes to [array get __ia]"
+ my set instance_attributes [array get __ia]
+ return [list $validation_errors $category_ids]
+ }
+
+ FormPage instproc form_field_as_html {{-mode edit} before name form_fields} {
+ set found 0
+ foreach f $form_fields {
+ if {[$f name] eq $name} {set found 1; break}
+ }
+ if {!$found} {
+ set f [my create_form_field -name $name -slot [my find_slot $name]]
+ }
+ #my msg "$name mode=$mode type=[$f set type]"
+ if {$mode eq "edit" || [$f display_field]} {
+ set html [$f asHTML]
+ } else {
+ set html @$name@
+ }
+ #my msg "$name $html"
+ return ${before}$html
+ }
+}
+
+namespace eval ::xowiki {
+
+ FormPage instproc create_form_fields {field_names} {
+
+ set form_fields [my create_category_fields]
+ set cr_field_spec [my get_short_spec @cr_fields]
+ set field_spec [my get_short_spec @fields]
+
+ foreach att $field_names {
+ switch -glob -- $att {
+ __* {}
+ _* {
+ set varname [string range $att 1 end]
+ lappend form_fields [my create_form_field -name $att \
+ -spec $cr_field_spec \
+ -slot [my find_slot $varname]]
+ }
+ default {
+ lappend form_fields [my create_form_field -name $att \
+ -spec $field_spec \
+ -slot [my find_slot $att]]
+ }
+ }
+ }
+ return $form_fields
+ }
+
+ FormPage instproc edit {
+ {-validation_errors ""}
+ } {
+ my instvar page_template doc root package_id
+
+ ::xowiki::Form requireFormCSS
+
+ set form [lindex [my get_from_template form] 0]
+ set anon_instances [my get_from_template anon_instances]
+
+ if {$form eq ""} {
+ #
+ # Since we have no form, we create it on the fly
+ # from the template variables and the form field specifications.
+ #
+ set form "
"
+ set formgiven 0
+ } else {
+ set formgiven 1
+ }
+
+ foreach {form_vars needed_attributes} [my form_attributes] break
+ #my msg "form_vars=$form_vars needed_attributes=$needed_attributes"
+ if {$form_vars} {foreach v $needed_attributes {set field_in_form($v) 1}}
+
+ #
+ # Remove the fields already included in auto_fields form the needed_attributes.
+ # The final list field_names determines the order of the fields in the form.
+ #
+ set auto_fields [list _name _page_order _creator _title _text _description _nls_language]
+ set reduced_attributes $needed_attributes
+
+ foreach f $auto_fields {
+ set p [lsearch $reduced_attributes $f]
+ if {$p > -1} {
+ #if {$form_vars} {
+ #set auto_field_in_form($f) 1
+ #}
+ set reduced_attributes [lreplace $reduced_attributes $p $p]
+ }
+ }
+ #my msg reduced_attributes=$reduced_attributes
+ #my msg fields_from_from=[array names field_in_form]
+
+ set field_names [list _name]
+ if {[$package_id show_page_order]} { lappend field_names _page_order }
+ lappend field_names _title _creator
+ foreach fn $reduced_attributes { lappend field_names $fn }
+ foreach fn [list _text _description _nls_language] { lappend field_names $fn }
+ #my msg field_names=$field_names
+
+ set form_fields [my create_form_fields $field_names]
+ if {$anon_instances} {
+ set f [my lookup_form_field -name _name $form_fields]
+ $f config_from_spec hidden
+ }
+ # include _text only, if explicitely needed (in form or template)
+ if {[lsearch $needed_attributes _text] == -1} {
+ #my msg "setting text hidden"
+ set f [my lookup_form_field -name _text $form_fields]
+ $f config_from_spec hidden
+ }
+ #my show_fields $form_fields
+
+ if {[my form_parameter __form_action ""] eq "save-form-data"} {
+ #my msg "we have to validate"
+ #
+ # we have to valiate and save the form data
+ #
+ foreach {validation_errors category_ids} [my get_form_data $form_fields] break
+ if {$validation_errors != 0} {
+ #my msg "$validation_errors errors in $form_fields"
+ #foreach f $form_fields { my msg "$f: [$f name] '[$f set value]' err: [$f error_msg] " }
+ # reset the name in error cases to the original one
+ my set name [my form_parameter __object_name]
+ } else {
+ #
+ # we have no validation erros, so we can save the content
+ #
+ my save_data [::xo::cc form_parameter __object_name ""] $category_ids
+ #my log "--forminstance redirect to [$package_id pretty_link [my name]]"
+ $package_id returnredirect \
+ [my query_parameter "return_url" [$package_id pretty_link [my name]]]
+ return
+ }
+ } else {
+ #
+ # display the current values
+ #
+
+ if {[my is_new_entry [my name]]} {
+ my set creator [::xo::get_user_name [::xo::cc user_id]]
+ my set nls_language [ad_conn locale]
+ }
+
+ array set __ia [my set instance_attributes]
+ foreach att $field_names {
+ switch -glob $att {
+ __* {}
+ _* {
+ set f [my lookup_form_field -name $att $form_fields]
+ set varname [string range $att 1 end]
+ $f value [my set $varname]
+ }
+ default {
+ set f [my lookup_form_field -name $att $form_fields]
+ if {[info exists __ia($att)]} {
+ $f value $__ia($att)
+ }
+ }
+ }
+ set ff($att) $f
+ }
+
+ # for named entries, just set the entry fields to empty,
+ # without changing the instance variables
+ if {[my is_new_entry [my name]]} {
+ if {![$ff(_title) istype ::xowiki::FormField::hidden]} {$ff(_title) value ""}
+ if {!$anon_instances} {$ff(_name) value ""}
+ }
+ }
+
+ # the following command wout be correct, but does not work due to a bug in
+ # tdom.
+ #set form [my regsub_eval \
+ # [template::adp_variable_regexp] $form \
+ # {my form_field_as_html "\\\1" "\2" $form_fields}]
+ # due to this bug, we replace the at-character by \x003 to avoid conflict withe the
+ # input and we insert the fields in the result from tdom.
+
+ set form [string map [list @ \x003] $form]
+ #my msg form=$form
+
+ dom parse -simple -html $form doc
+ $doc documentElement root
+
+ ::require_html_procs
+ $root firstChild fcn
+ #
+ # prepend some fields above the HTML contents of the form
+ #
+ $root insertBeforeFromScript {
+ ::html::input -type hidden -name __object_name -value [my name]
+ ::html::input -type hidden -name __form_action -value save-form-data
+
+ # insert automatic form fields on top
+ foreach att $field_names {
+ #if {$formgiven && ![string match _* $att]} continue
+ if {[info exists field_in_form($att)]} continue
+ set f [my lookup_form_field -name $att $form_fields]
+ #my msg "insert auto_field $att"
+ $f render_item
+ }
+ } $fcn
+ #
+ # append some fields after the HTML contents of the form
+ #
+ set submit_button_class ""
+ $root appendFromScript {
+ # append category fields
+ foreach f $form_fields {
+ if {[string match "__category_*" [$f name]]} {
+ $f render_item
+ } elseif {[$f info class] eq "::xowiki::FormField::richtext::wym"} {
+ set submit_button_class "wymupdate"
+ }
+ }
+
+ # insert unreported errors and add a submit field at bottom
+ foreach f $form_fields {
+ if {[$f set error_msg] ne "" && ![$f exists error_reported]} {
+ $f render_error_msg
+ }
+ }
+ set f [::xowiki::FormField::submit_button new -destroy_on_cleanup \
+ -name __form_button_ok \
+ -CSSclass $submit_button_class]
+ $f render_content
+ }
+ set form [lindex [$root selectNodes //form] 0]
+ if {$form eq ""} {
+ my msg "no form found in page [$page_template name]"
+ } else {
+ if {[my exists_query_parameter "return_url"]} {
+ set return_url [my query_parameter "return_url"]
+ }
+ set url [export_vars -base [$package_id pretty_link [my name]] {{m "edit"} return_url}]
+ $form setAttribute action $url method POST
+ set oldCSSClass [expr {[$form hasAttribute class] ? [$form getAttribute class] : ""}]
+ $form setAttribute class [string trim "$oldCSSClass margin-form"]
+ }
+ my set_form_data
+ set html [$root asHTML]
+
+ set html [my regsub_eval \
+ {(^|[^\\])\x003([a-zA-Z0-9_:]+)\x003} $html \
+ {my form_field_as_html "\\\1" "\2" $form_fields}]
+
+ #my msg result=$html
+ my view $html
+ }
+
+
+
+ File instproc download {} {
+ my instvar text mime_type package_id item_id revision_id
+ $package_id set mime_type $mime_type
+ set use_bg_delivery [expr {![catch {ns_conn contentsentlength}] &&
+ [info command ::bgdelivery] ne ""}]
+ $package_id set delivery \
+ [expr {$use_bg_delivery ? "ad_returnfile_background" : "ns_returnfile"}]
+ #my log "--F FILE=[my full_file_name]"
+ return [my full_file_name]
+ }
+
+ Page instproc revisions {} {
+ my instvar package_id name item_id
+ set context [list [list [$package_id url] $name ] [_ xotcl-core.revisions]]
+ set title "[_ xotcl-core.revision_title] '$name'"
+ set content [next]
+ $package_id return_page -adp /packages/xowiki/www/revisions -variables {
+ content context {page_id $item_id} title
+ }
+ }
+
+ Page instproc make-live-revision {} {
+ my instvar revision_id item_id package_id
+ #my log "--M set_live_revision($revision_id)"
+ ::xo::db::sql::content_item set_live_revision -revision_id $revision_id
+ set page_id [my query_parameter "page_id"]
+ ns_cache flush xotcl_object_cache ::$item_id
+ ::$package_id returnredirect [my query_parameter "return_url" \
+ [export_vars -base [$package_id url] {{m revisions}}]]
+ }
+
+
+ Page instproc delete-revision {} {
+ my instvar revision_id package_id item_id
+ db_1row [my qn get_revision] "select latest_revision,live_revision from cr_items where item_id = $item_id"
+ ns_cache flush xotcl_object_cache ::$item_id
+ ns_cache flush xotcl_object_cache ::$revision_id
+ ::xo::db::sql::content_revision del -revision_id $revision_id
+ set redirect [my query_parameter "return_url" \
+ [export_vars -base [$package_id url] {{m revisions}}]]
+ if {$live_revision == $revision_id} {
+ # latest revision might have changed by delete_revision, so we have to fetch here
+ db_1row [my qn get_revision] "select latest_revision from cr_items where item_id = $item_id"
+ if {$latest_revision eq ""} {
+ # we are out of luck, this was the final revision, delete the item
+ my instvar package_id name
+ $package_id delete -name $name -item_id $item_id
+ } else {
+ ::xo::db::sql::content_item set_live_revision -revision_id $latest_revision
+ }
+ }
+ if {$latest_revision ne ""} {
+ # otherwise, "delete" did already the redirect
+ ::$package_id returnredirect [my query_parameter "return_url" \
+ [export_vars -base [$package_id url] {{m revisions}}]]
+ }
+ }
+
+ Page instproc delete {} {
+ my instvar package_id item_id name
+ [my info class] delete -item_id $item_id
+ ::$package_id flush_references -item_id $item_id -name $name
+ ::$package_id returnredirect \
+ [my query_parameter "return_url" [$package_id package_url]]
+ }
+
+ Page instproc save-tags {} {
+ my instvar package_id item_id
+ ::xowiki::Page save_tags -user_id [::xo::cc user_id] -item_id $item_id \
+ -package_id $package_id [my form_parameter new_tags]
+
+ ::$package_id returnredirect \
+ [my query_parameter "return_url" [$package_id url]]
+ }
+
+ Page instproc popular-tags {} {
+ my instvar package_id item_id parent_id
+ set limit [my query_parameter "limit" 20]
+ set weblog_page [$package_id get_parameter weblog_page weblog]
+ set href [$package_id pretty_link $weblog_page]?summary=1
+
+ set entries [list]
+ db_foreach [my qn get_popular_tags] \
+ [::xo::db::sql \
+ -vars "count(*) as nr, tag" \
+ -from "xowiki_tags" \
+ -where "item_id=$item_id" \
+ -groupby "tag" \
+ -orderby "nr" \
+ -limit $limit] {
+ lappend entries "
$tag ($nr) "
+ }
+ ns_return 200 text/html "[_ xowiki.popular_tags_label]: [join $entries {, }]"
+ }
+
+ Page instproc diff {} {
+ my instvar package_id
+ set compare_id [my query_parameter "compare_revision_id" 0]
+ if {$compare_id == 0} {
+ return ""
+ }
+ set my_page [::xowiki::Package instantiate_page_from_id -revision_id [my set revision_id]]
+ $my_page volatile
+
+ set html1 [$my_page render]
+ set text1 [ad_html_text_convert -from text/html -to text/plain -- $html1]
+ set user1 [::xo::get_user_name [$my_page set creation_user]]
+ set time1 [$my_page set creation_date]
+ set revision_id1 [$my_page set revision_id]
+ regexp {^([^.]+)[.]} $time1 _ time1
+
+ set other_page [::xowiki::Package instantiate_page_from_id -revision_id $compare_id]
+ $other_page volatile
+ #$other_page absolute_links 1
+
+ set html2 [$other_page render]
+ set text2 [ad_html_text_convert -from text/html -to text/plain -- $html2]
+ set user2 [::xo::get_user_name [$other_page set creation_user]]
+ set time2 [$other_page set creation_date]
+ set revision_id2 [$other_page set revision_id]
+ regexp {^([^.]+)[.]} $time2 _ time2
+
+ set title "Differences for [my set name]"
+ set context [list $title]
+
+ set content [::xowiki::html_diff $text2 $text1]
+ $package_id return_page -adp /packages/xowiki/www/diff -variables {
+ content title context
+ time1 time2 user1 user2 revision_id1 revision_id2
+ }
+ }
+
+ proc html_diff {doc1 doc2} {
+ set out ""
+ set i 0
+ set j 0
+
+ #set lines1 [split $doc1 "\n"]
+ #set lines2 [split $doc2 "\n"]
+
+ regsub -all \n $doc1 "
" doc1
+ regsub -all \n $doc2 "
" doc2
+ set lines1 [split $doc1 " "]
+ set lines2 [split $doc2 " "]
+
+ foreach { x1 x2 } [list::longestCommonSubsequence $lines1 $lines2] {
+ foreach p $x1 q $x2 {
+ while { $i < $p } {
+ set l [lindex $lines1 $i]
+ incr i
+ #puts "R\t$i\t\t$l"
+ append out "
$l \n"
+ }
+ while { $j < $q } {
+ set m [lindex $lines2 $j]
+ incr j
+ #puts "A\t\t$j\t$m"
+ append out "
$m \n"
+ }
+ set l [lindex $lines1 $i]
+ incr i; incr j
+ #puts "B\t$i\t$j\t$l"
+ append out "$l\n"
+ }
+ }
+ while { $i < [llength $lines1] } {
+ set l [lindex $lines1 $i]
+ incr i
+ puts "$i\t\t$l"
+ append out "
$l \n"
+ }
+ while { $j < [llength $lines2] } {
+ set m [lindex $lines2 $j]
+ incr j
+ #puts "\t$j\t$m"
+ append out "
$m \n"
+ }
+ return $out
+ }
+
+
+# Page instproc new_name {name} {
+# if {$name ne ""} {
+# my instvar package_id
+# set name [my complete_name $name]
+# set name [::$package_id normalize_name $name]
+# set suffix ""; set i 0
+# set folder_id [my parent_id]
+# while {[CrItem lookup -name $name$suffix -parent_id $folder_id] != 0} {
+# set suffix -[incr i]
+# }
+# set name $name$suffix
+# }
+# return $name
+# }
+
+# Page instproc create-new {} {
+# my instvar package_id
+# set name [my new_name [::xo::cc form_parameter name ""]]
+# set class [::xo::cc form_parameter class ::xowiki::Page]
+# if {[::xotcl::Object isclass $class] && [$class info heritage ::xowiki::Page] ne ""} {
+# set class [::xo::cc form_parameter class ::xowiki::Page]
+# set f [$class new -destroy_on_cleanup \
+# -name $name \
+# -package_id $package_id \
+# -parent_id [my parent_id] \
+# -publish_status "production" \
+# -title [my title] \
+# -text [list [::xo::cc form_parameter content ""] text/html]]
+# $f save_new
+# $package_id returnredirect \
+# [my query_parameter "return_url" [$package_id pretty_link $name]?m=edit]
+# }
+# }
+
+ PageTemplate instproc delete {} {
+ my instvar package_id item_id name
+ set count [my count_usages -all true]
+ #my msg count=$count
+ if {$count > 0} {
+ append error_msg \
+ [_ xowiki.error-delete_entries_first [list count $count]] \
+
\
+ [my include_portlet [list form-usages -all true -form_item_id [my item_id]]] \
+
+ $package_id error_msg $error_msg
+ } else {
+ next
+ }
+ }
+
+ Form instproc create-new {} {
+ my instvar package_id
+ set f [FormPage new -destroy_on_cleanup \
+ -package_id $package_id \
+ -parent_id [my parent_id] \
+ -publish_status "production" \
+ -page_template [my item_id]]
+
+ # set some default values if they are provided
+ foreach key {name title page_order last_page_id} {
+ if {[$package_id exists_query_parameter $key]} {
+ $f set $key [$package_id query_parameter $key]
+ }
+ }
+ $f set __title_prefix [my title]
+ $f save_new
+ if {[my exists_query_parameter "return_url"]} {
+ set return_url [my query_parameter "return_url"]
+ }
+ $package_id returnredirect \
+ [export_vars -base [$package_id pretty_link [$f name]] {{m edit} return_url}]
+ }
+
+
+ if {[apm_version_names_compare [ad_acs_version] 5.3.0] == 1} {
+ ns_log notice "Zen-state: 5.3.2 or newer"
+ Form set extraCSS ""
+ } else {
+ ns_log notice "Zen-state: pre 5.3.1, use backward compatible form css file"
+ Form set extraCSS "zen-forms-backward-compatibility.css"
+ }
+ Form proc requireFormCSS {} {
+ #my msg requireFormCSS
+ set css [my set extraCSS]
+ if {$css ne ""} {
+ #my msg "requireCSS $css"
+ ::xowiki::Page requireCSS $css
+ }
+ }
+
+}
\ No newline at end of file
Index: openacs-4/packages/xowiki/www/diff.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/diff.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/diff.adp 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,29 @@
+
+ @title;noquote@
+ @context;noquote@
+
+
+
+
+
+
+
+ Comparing
+
+version @revision_id1@ modified by @user1@ at @time1@ with
+ version @revision_id2@ modified by @user2@ at @time2@
+
+
+
+
+@content;noquote@
+
Index: openacs-4/packages/xowiki/www/edit.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/Attic/edit.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/edit.adp 1 Aug 2007 21:39:25 -0000 1.3.2.2
@@ -0,0 +1,23 @@
+
+ @edit_form_page_title;noquote@
+ @context;noquote@
+ note.title
+
+
+
+
+
+
Index: openacs-4/packages/xowiki/www/error-template.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/error-template.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/error-template.adp 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,24 @@
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+ @header_stuff;noquote@
+
+
+
+
+
+
+
Error:
+
+
+@error_msg;noquote@
+
+
+
+
Index: openacs-4/packages/xowiki/www/index.vuh
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/index.vuh,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/index.vuh 1 Aug 2007 21:39:25 -0000 1.5.2.2
@@ -0,0 +1,24 @@
+# -*- tcl -*-
+::xowiki::Package initialize -ad_doc {
+
+ This is the resolver for this package. It turns a request into
+ an object and executes the object with the computed method
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date July, 2006
+ @cvs-id $Id: index.vuh,v 1.5.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+} -parameter {
+ {-m view}
+ {-folder_id:integer 0}
+}
+
+::$package_id log "--starting... [ns_conn url] [ns_conn query] \
+ form vars = [ns_set array [ns_getform]]"
+#::$package_id exists_form_parameter creator
+#::$package_id log "-- [::xo::cc serialize]"
+
+::$package_id reply_to_user [::$package_id invoke -method $m]
+
+::$package_id log "--i ::$package_id DONE"
+ad_script_abort
Index: openacs-4/packages/xowiki/www/oacs-view.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/oacs-view.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/oacs-view.adp 1 Aug 2007 21:39:25 -0000 1.39.2.2
@@ -0,0 +1,85 @@
+
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+
+
+
+
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+
+
+@footer;noquote@
+
Index: openacs-4/packages/xowiki/www/oacs-view2.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/oacs-view2.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/oacs-view2.adp 1 Aug 2007 21:39:25 -0000 1.18.2.2
@@ -0,0 +1,117 @@
+
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+
+
+
+
+
+@footer;noquote@
+
Index: openacs-4/packages/xowiki/www/oacs-view3.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/oacs-view3.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/oacs-view3.adp 1 Aug 2007 21:39:25 -0000 1.13.2.2
@@ -0,0 +1,117 @@
+
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+
+
+@footer;noquote@
+
Index: openacs-4/packages/xowiki/www/portlet-ajax.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/portlet-ajax.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/portlet-ajax.adp 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1,24 @@
+
+@title@
+
+
+
+... loading ....
+
Index: openacs-4/packages/xowiki/www/portlet-ajax.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/portlet-ajax.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/portlet-ajax.tcl 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1,8 @@
+# like portlet, except with background loading via ajax
+# gustaf neumann, fecit may 2006
+::xowiki::Page requireJS "/resources/xowiki/get-http-object.js"
+if {![string match "/*" $portlet]} {
+ set folder_id [$__including_page set parent_id]
+ set package_id [$folder_id set package_id]
+ set portlet [site_node::get_url_from_object_id -object_id $package_id]portlets/$portlet
+}
Index: openacs-4/packages/xowiki/www/portlet.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/portlet.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/portlet.adp 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1,6 @@
+
+@title@
+
+
+
+
Index: openacs-4/packages/xowiki/www/portlet.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/portlet.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/portlet.tcl 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,4 @@
+#
+if {![string match "/*" $portlet]} {
+ set portlet /packages/xowiki/www/portlets/$portlet
+}
Index: openacs-4/packages/xowiki/www/revisions.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/revisions.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/revisions.adp 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,15 @@
+
+@title;noquote@
+@title;noquote@
+@context;noquote@
+@page_id;noquote@
+
+@content;noquote@
+
+
+ #file-storage.lt_Comments_on_this_file#
+
+
+
+ @gc_link;noquote@
+
Index: openacs-4/packages/xowiki/www/view-book.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-book.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-book.adp 1 Aug 2007 21:39:25 -0000 1.10.2.2
@@ -0,0 +1,93 @@
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+
+
+
+
+
@top_portlets;noquote@
+
+
+
+
+
+
+
+
+
+
+@footer;noquote@
+
Index: openacs-4/packages/xowiki/www/view-book.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-book.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-book.tcl 1 Aug 2007 21:39:25 -0000 1.5.2.2
@@ -0,0 +1,22 @@
+set title [[$package_id folder_id] title]
+set toc [$page include_portlet [list toc -open_page $name -decoration plain -remove_levels 1]]
+set i [$page set __last_includelet]
+#my log "--last includelet = $i, class=[$i info class] [$page exists __is_book_page]"
+
+if {$i ne "" && ![$page exists __is_book_page]} {
+ set p [$i position]
+ set count [$i count]
+ #my log "--toc count=$count size=[$i array size page_name] indices=[lsort -integer [$i array names page_name]]"
+ if {$count > 0} {
+ set book_relpos [format %.2f%% [expr {100.0 * $p / $count}]]
+
+ if {$p>1} {set book_prev_link [$package_id pretty_link [$i page_name [expr {$p - 1}]]]}
+ if {$p<$count} {set book_next_link [$package_id pretty_link [$i page_name [expr {$p + 1}]]]}
+ #ns_log notice "--p=$p, count=$count, relpos=$book_relpos, {100.0 * $p / $count} next=[info exists next_link], prev=[info exists prev_link]"
+ set page_title "[$i current] $title "
+ } else {
+ set book_relpos 0.0%
+ set page_title "$title "
+ }
+}
+set header_stuff [::xowiki::Page header_stuff]
Index: openacs-4/packages/xowiki/www/view-default.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-default.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-default.adp 1 Aug 2007 21:39:25 -0000 1.35.2.2
@@ -0,0 +1,67 @@
+
+
+ @title;noquote@
+ @context;noquote@
+ @header_stuff;noquote@
+
+
+
+ @header_stuff;noquote@
+
+
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+@footer;noquote@
+
Index: openacs-4/packages/xowiki/www/view-links.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-links.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-links.adp 1 Aug 2007 21:39:25 -0000 1.25.2.2
@@ -0,0 +1,22 @@
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+
+
Index: openacs-4/packages/xowiki/www/view-page.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-page.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-page.adp 1 Aug 2007 21:39:25 -0000 1.3.2.2
@@ -0,0 +1,25 @@
+
+
+
+
+@page_title@
+
+
+@content;noquote@
+
Index: openacs-4/packages/xowiki/www/view-page.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-page.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-page.tcl 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1 @@
+set page_title "[$page set page_order] [$page set title]"
\ No newline at end of file
Index: openacs-4/packages/xowiki/www/view-plain.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/view-plain.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/view-plain.adp 1 Aug 2007 21:39:25 -0000 1.21.2.2
@@ -0,0 +1,9 @@
+
+
+
+
+
+@top_portlets;noquote@
+@content;noquote@
+
+
Index: openacs-4/packages/xowiki/www/admin/delete-type.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/delete-type.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/delete-type.tcl 1 Aug 2007 21:39:25 -0000 1.9.2.2
@@ -0,0 +1,24 @@
+::xowiki::Package initialize -ad_doc {
+ This deletes a type with all subtypes and instances
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Aug 11, 2006
+ @cvs-id $Id: delete-type.tcl,v 1.9.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+ @param object_type
+ @param query
+} -parameter {
+ {-object_type ::xowiki::Page}
+ {-return_url "."}
+}
+
+set sql [$object_type instance_select_query -with_subtypes 0 -folder_id [::$package_id folder_id]]
+db_foreach retrieve_instances $sql {
+ permission::require_write_permission -object_id $item_id
+ $object_type delete -item_id $item_id
+}
+
+# drop type requires that all pages of all xowiki instances are deleted
+#foreach type [$object_type object_types -subtypes_first true] {$type drop_object_type}
+
+ad_returnredirect $return_url
Index: openacs-4/packages/xowiki/www/admin/export.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/export.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/export.tcl 1 Aug 2007 21:39:25 -0000 1.5.2.2
@@ -0,0 +1,49 @@
+::xowiki::Package initialize -ad_doc {
+ export the objects of the specified type
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Aug 11, 2006
+ @cvs-id $Id: export.tcl,v 1.5.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+ @param object_type
+} -parameter {
+ {-object_type ::xowiki::Page}
+ {-objects ""}
+}
+
+set folder_id [::$package_id folder_id]
+set item_ids [list]
+
+if {$objects eq ""} {
+ set sql [$object_type instance_select_query -folder_id $folder_id \
+ -with_subtypes true]
+ db_foreach instance_select $sql { lappend item_ids $item_id }
+} else {
+ foreach o $objects {
+ if {[set id [CrItem lookup -name $o -parent_id $folder_id]] != 0} {
+ lappend item_ids $id
+ }
+ }
+}
+
+set content ""
+foreach item_id $item_ids {
+ ::Generic::CrItem instantiate -item_id $item_id
+ #
+ # if the page belongs to an Form/PageTemplate, include it as well
+ #
+ if {[$item_id istype ::xowiki::PageInstance]} {
+ set template_id [$item_id page_template]
+ if {[lsearch $item_ids $template_id] == -1 &&
+ ![info exists included($template_id)]} {
+ ::Generic::CrItem instantiate -item_id $template_id
+ $template_id volatile
+ append content [$template_id marshall] \n
+ set included($template_id) 1
+ }
+ }
+ $item_id volatile
+ append content [$item_id marshall] \n
+}
+
+ns_return 200 text/plain $content
Index: openacs-4/packages/xowiki/www/admin/import.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/import.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/import.adp 1 Aug 2007 21:39:25 -0000 1.3.2.2
@@ -0,0 +1,29 @@
+
+ @title;noquote@
+ @context;noquote@
+
+
+
+
+
+
+
+
+
+
+
+
+ @formerror.upload_file@
+
+
+
+
+
+
+
+
+
+
+@msg;noquote@
+Index
+
Index: openacs-4/packages/xowiki/www/admin/import.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/import.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/import.tcl 1 Aug 2007 21:39:25 -0000 1.10.2.2
@@ -0,0 +1,44 @@
+::xowiki::Package initialize -ad_doc {
+ import objects in xotcl format
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Aug 11, 2006
+ @cvs-id $Id: import.tcl,v 1.10.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+}
+
+set msg ""
+ad_form \
+ -name upload_form \
+ -mode edit \
+ -export {fs_package_id folder_id orderby selector_type file_types} \
+ -html { enctype multipart/form-data } \
+ -form {
+ {upload_file:file(file) {html {size 30}} }
+ {ok_btn:text(submit) {label "[_ acs-templating.HTMLArea_SelectUploadBtn]"}
+ }
+ } \
+ -on_submit {
+ # check file name
+ if {$upload_file eq ""} {
+ template::form::set_error upload_form upload_file \
+ [_ acs-templating.HTMLArea_SpecifyUploadFilename]
+ break
+ }
+
+ set upload_tmpfile [template::util::file::get_property tmp_filename $upload_file]
+ set f [open $upload_tmpfile]; set content [read $f]; close $f
+
+ foreach o [::xowiki::Page allinstances] { $o destroy }
+ if {[catch {namespace eval ::xo::import $content} error]} {
+ set msg "Error: $error"
+ } else {
+ set msg [$package_id import -replace 0]
+ }
+ namespace delete ::xo::import
+ }
+
+
+set title "Import XoWiki Pages"
+set context .
+ad_return_template
Index: openacs-4/packages/xowiki/www/admin/importmsg.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/importmsg.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/importmsg.adp 1 Aug 2007 21:39:25 -0000 1.3.2.2
@@ -0,0 +1,7 @@
+
+ @title;noquote@
+ @context;noquote@
+
+@msg;noquote@
+Index
+
Index: openacs-4/packages/xowiki/www/admin/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/index.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/index.adp 1 Aug 2007 21:39:25 -0000 1.5.2.2
@@ -0,0 +1,24 @@
+
+ @title;noquote@
+ @context;noquote@
+
+
+
+Site-Wide Categories
+
+@t1;noquote@
+
+
Index: openacs-4/packages/xowiki/www/admin/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/index.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/index.tcl 1 Aug 2007 21:39:25 -0000 1.18.2.2
@@ -0,0 +1,67 @@
+::xowiki::Package initialize -ad_doc {
+
+ This is the admin page for the package. It displays all of the types
+ of wiki pages provides links to delete them
+
+ @author Gustaf Neumann neumann@wu-wien.ac.at
+ @cvs-id $Id: index.tcl,v 1.18.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+} -parameter {
+ {-object_type ::xowiki::Page}
+}
+
+set context [list]
+set title "Administer all kind of [$object_type set pretty_plural]"
+
+set object_type_key [$object_type set object_type_key]
+set object_types [$object_type object_types]
+set return_url [ns_conn url]
+
+TableWidget t1 -volatile \
+ -actions [subst {
+ Action new -label "all pages" -url list
+ Action new -label parameters -url \
+ [export_vars -base /shared/parameters {package_id return_url}]
+ Action new -label export -url export
+ Action new -label import -url import
+ Action new -label permissions -url [export_vars -base permissions {package_id}]
+ }] \
+ -columns {
+ Field object_type -label [_ xowiki.page_type]
+ AnchorField instances -label Instances -html {align center}
+ ImageField_AddIcon edit -label "Add" -html {align center}
+ ImageField_DeleteIcon delete -label "Delete All" \
+ -html {align center onClick "return(confirm('Delete really all?'));"}
+ }
+
+set base [::$package_id package_url]
+foreach object_type $object_types {
+ set return_url [export_vars -base ${base}admin {object_type}]
+ if {[catch {set n [db_list count [$object_type instance_select_query \
+ -folder_id [::$package_id set folder_id] \
+ -count 1 -with_subtypes false]]}]} {
+ set n -
+ set add_title ""
+ set add_href ""
+ set delete_title "Delete all such items of this instance"
+ } else {
+ set add_title [_ xotcl-core.add [list type [$object_type pretty_name]]]
+ set add_href [$package_id make_link $package_id edit-new object_type return_url autoname]
+ set delete_title "Delete all [$object_type pretty_plural] of this instance"
+ }
+ t1 add \
+ -object_type $object_type \
+ -instances $n \
+ -instances.href [export_vars -base ./list {object_type}] \
+ -edit.href $add_href \
+ -delete.href [export_vars -base delete-type {object_type}] \
+ -edit.title $add_title \
+ -delete.title $delete_title
+}
+
+set t1 [t1 asHTML]
+
+# set up categories
+set category_map_url [export_vars -base \
+ [site_node::get_package_url -package_key categories]cadmin/object-map \
+ { { object_id $package_id } }]
\ No newline at end of file
Index: openacs-4/packages/xowiki/www/admin/list.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/list.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/list.adp 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1,24 @@
+
+ @title;noquote@
+ @context;noquote@
+
+
+
+
+Site-Wide Categories...
+
+@t1;noquote@
+
Index: openacs-4/packages/xowiki/www/admin/list.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/list.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/list.tcl 1 Aug 2007 21:39:25 -0000 1.15.2.2
@@ -0,0 +1,146 @@
+::xowiki::Package initialize -ad_doc {
+ This is the admin page for the package. It displays all entries
+ provides links to create, edit and delete these
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Oct 23, 2005
+ @cvs-id $Id: list.tcl,v 1.15.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+ @param object_type show objects of this class and its subclasses
+} -parameter {
+ {-object_type:optional}
+ {-orderby:optional "last_modified,desc"}
+}
+
+set context [list index]
+
+# if object_type is specified, only list entries of this type;
+# otherwise show types and subtypes of $supertype
+if {![info exists object_type]} {
+ set per_type 0
+ set supertype ::xowiki::Page
+ set object_types [$supertype object_types]
+ set title "List of all kind of [$supertype set pretty_plural]"
+ set with_subtypes true
+ set object_type $supertype
+} else {
+ set per_type 1
+ set object_types [list $object_type]
+ set title "Index of [$object_type set pretty_plural]"
+ set with_subtypes false
+}
+
+set return_url [expr {$per_type ? [export_vars -base [::$package_id url] object_type] :
+ [::$package_id url]}]
+# set up categories
+set category_map_url [export_vars -base \
+ [site_node::get_package_url -package_key categories]cadmin/one-object \
+ { { object_id $package_id } }]
+
+set actions ""
+foreach type $object_types {
+ append actions [subst {
+ Action new \
+ -label "[_ xotcl-core.add [list type [$type pretty_name]]]" \
+ -url [export_vars -base [::$package_id package_url] {{edit-new 1} {object_type $type} return_url}] \
+ -tooltip "[_ xotcl-core.add_long [list type [$type pretty_name]]]"
+ }]
+}
+
+set ::individual_permissions [expr {[$package_id set policy] eq "::xowiki::policy3"}]
+set ::with_publish_status 1
+
+TableWidget t1 -volatile \
+ -actions $actions \
+ -columns {
+ BulkAction objects -id name -actions {
+ Action new -label export -tooltip export -url export
+ }
+ ImageField_EditIcon edit -label "" -html {style "padding: 2px;"}
+ if {$::individual_permissions} {
+ ImageAnchorField permissions -src /resources/xowiki/permissions.png -width 16 \
+ -height 16 -border 0 -title "Manage Individual Permssions for this Item" \
+ -alt permsissions -label "" -html {style "padding: 2px;"}
+ }
+ if {$::with_publish_status} {
+ ImageAnchorField publish_status -src "" -width 8 \
+ -height 8 -border 0 -title "Toggle Publish Status" \
+ -alt "publish status" -label [_ xowiki.publish_status] -html {style "padding: 2px;"}
+ }
+ Field syndicated -label "RSS" -html {style "padding: 2px;"}
+ if {[::xo::db::has_ltree]} {
+ AnchorField page_order -label [_ xowiki.order] -orderby page_order -html {style "padding: 2px;"}
+ }
+ AnchorField name -label [_ xowiki.Page-name] -orderby name -html {style "padding: 2px;"}
+ AnchorField title -label [_ xowiki.Page-title] -orderby title
+ Field object_type -label [_ xowiki.page_type] -orderby object_type -html {style "padding: 2px;"}
+ Field size -label "Size" -orderby size -html {align right style "padding: 2px;"}
+ Field last_modified -label "Last Modified" -orderby last_modified
+ Field mod_user -label "By User" -orderby mod_user
+ ImageField_DeleteIcon delete -label "" ;#-html {onClick "return(confirm('Confirm delete?'));"}
+ }
+
+foreach {att order} [split $orderby ,] break
+t1 orderby -order [expr {$order eq "asc" ? "increasing" : "decreasing"}] $att
+
+# -page_size 10
+# -page_number 1
+
+set attributes [list revision_id content_length creation_user title \
+ "to_char(last_modified,'YYYY-MM-DD HH24:MI:SS') as last_modified"]
+if {[::xo::db::has_ltree]} {
+ lappend attributes page_order
+}
+
+set folder_id [::$package_id folder_id]
+foreach i [db_list get_syndicated {
+ select object_id from syndication s, cr_items ci
+ where object_id = ci.live_revision and parent_id = :folder_id
+}] { set syndicated($i) 1 }
+
+db_foreach instance_select \
+ [$object_type instance_select_query \
+ -folder_id $folder_id \
+ -with_subtypes $with_subtypes \
+ -from_clause ", xowiki_page p" \
+ -where_clause "p.page_id = cr.revision_id" \
+ -select_attributes $attributes \
+ -orderby ci.name \
+ ] {
+ set page_link [::$package_id pretty_link $name]
+
+ t1 add \
+ -name $name \
+ -title $title \
+ -object_type [string map [list "::xowiki::" ""] $object_type] \
+ -name.href $page_link \
+ -last_modified $last_modified \
+ -syndicated [info exists syndicated($revision_id)] \
+ -size [expr {$content_length ne "" ? $content_length : 0}] \
+ -edit.href [export_vars -base $page_link {{m edit} return_url}] \
+ -mod_user [::xo::get_user_name $creation_user] \
+ -delete.href [export_vars -base [$package_id package_url] {{delete 1} item_id name return_url}]
+ if {$::individual_permissions} {
+ [t1 last_child] set permissions.href \
+ [export_vars -base permissions {item_id return_url}]
+ }
+ if {$::with_publish_status} {
+ # TODO: this should get some architectural support
+ if {$publish_status eq "ready"} {
+ set image active.png
+ set state "production"
+ } else {
+ set image inactive.png
+ set state "ready"
+ }
+ [t1 last_child] set publish_status.src /resources/xowiki/$image
+ [t1 last_child] set publish_status.href \
+ [export_vars -base [$package_id package_url]admin/set-publish-state \
+ {state revision_id return_url}]
+ }
+ if {[::xo::db::has_ltree]} {
+ [t1 last_child] set page_order $page_order
+ }
+ }
+
+set t1 [t1 asHTML]
Index: openacs-4/packages/xowiki/www/admin/permissions.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/permissions.adp,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/permissions.adp 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,5 @@
+
+ @page_title@
+ @context@
+
+
Index: openacs-4/packages/xowiki/www/admin/permissions.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/permissions.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/permissions.tcl 1 Aug 2007 21:39:25 -0000 1.2.2.2
@@ -0,0 +1,26 @@
+::xowiki::Package initialize -ad_doc {
+ Security management for xowiki pages
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Aug 16, 2006
+ @cvs-id $Id: permissions.tcl,v 1.2.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+} -parameter {
+ {-item_id:optional}
+}
+
+if {[info exists item_id]} {
+ set page [::Generic::CrItem instantiate -item_id $item_id]
+ $page volatile
+ set object_id $item_id
+ set page_title "Manage Permissions for Page: [$page name]"
+ set return_url [$package_id query_parameter return_url [$package_id package_url]admin/list]
+} else {
+ set object_id $package_id
+ set page_title "Manage Permissions for Package [apm_instance_name_from_id $package_id]"
+ set return_url [$package_id query_parameter return_url [$package_id package_url]admin]
+}
+
+set context [list $page_title]
+
+
Index: openacs-4/packages/xowiki/www/admin/portal-element-add.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/portal-element-add.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/portal-element-add.tcl 1 Aug 2007 21:39:25 -0000 1.5.2.2
@@ -0,0 +1,45 @@
+::xowiki::Package initialize -ad_doc {
+ Add an element to a given portal
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Oct 23, 2005
+ @cvs-id $Id: portal-element-add.tcl,v 1.5.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+ @param object_type show objects of this class and its subclasses
+} -parameter {
+ {-portal_id}
+ {-page_name}
+ {-referer .}
+}
+
+
+set page_id [$package_id resolve_request -path $page_name method]
+set page_id [::Generic::CrItem lookup -name $page_name -parent_id [$package_id folder_id]]
+set page_title [$page_id title]
+
+# for the time being, we add the portlet on the first page (page 0)
+set portal_page_id [portal::get_page_id -portal_id $portal_id -sort_key 0]
+
+if {[db_string check_unique_name_on_page {
+ select 1 from portal_element_map
+ where page_id = :portal_page_id
+ and pretty_name = :page_title
+} -default 0]} {
+ ad_return_error [_ xowiki.portlet_title_exists_error_short] [_ xowiki.portlet_title_exists_error_long]
+} else {
+ db_transaction {
+ set element_id [portal::add_element \
+ -portal_id $portal_id \
+ -portlet_name [xowiki_portlet::get_my_name] \
+ -pretty_name $page_title \
+ -force_region [parameter::get_from_package_key \
+ -parameter "xowiki_portal_content_force_region" \
+ -package_key "xowiki-portlet"]
+ ]
+ portal::set_element_param $element_id package_id $package_id
+ portal::set_element_param $element_id page_name [$page_id name]
+ }
+ ad_returnredirect $referer
+}
+ad_script_abort
+
Index: openacs-4/packages/xowiki/www/admin/portal-element-remove.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/portal-element-remove.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/portal-element-remove.tcl 1 Aug 2007 21:39:25 -0000 1.1.2.2
@@ -0,0 +1,19 @@
+::xowiki::Package initialize -ad_doc {
+ Add an element to a given portal
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Oct 23, 2005
+ @cvs-id $Id: portal-element-remove.tcl,v 1.1.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+} -parameter {
+ {-element_id}
+ {-portal_id}
+ {-referer .}
+}
+
+# permissions?
+portal::remove_element -element_id $element_id
+# redirect and abort
+ad_returnredirect $referer
+ad_script_abort
+
Index: openacs-4/packages/xowiki/www/admin/set-publish-state.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/set-publish-state.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/set-publish-state.tcl 1 Aug 2007 21:39:25 -0000 1.7.2.2
@@ -0,0 +1,33 @@
+::xowiki::Package initialize -ad_doc {
+ Changes the publication state of a content item
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Nov 16, 2006
+ @cvs-id $Id: set-publish-state.tcl,v 1.7.2.2 2007/08/01 21:39:25 gustafn Exp $
+
+ @param object_type
+ @param query
+} -parameter {
+ {-state:required}
+ {-revision_id:required}
+ {-return_url "."}
+}
+
+set item_id [db_string get_item_id \
+ {select item_id from cr_revisions where revision_id = :revision_id}]
+
+ns_cache flush xotcl_object_cache ::$item_id
+ns_cache flush xotcl_object_cache ::$revision_id
+
+::xo::db::sql::content_item set_live_revision \
+ -revision_id $revision_id \
+ -publish_status $state
+
+if {$state ne "production"} {
+ ::xowiki::notification::do_notifications -revision_id $revision_id
+ ::xowiki::datasource $revision_id
+} else {
+ db_dml flush_syndication {delete from syndication where object_id = :revision_id}
+}
+
+ad_returnredirect $return_url
Index: openacs-4/packages/xowiki/www/admin/test.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/test.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/test.tcl 1 Aug 2007 21:39:25 -0000 1.9.2.2
@@ -0,0 +1,514 @@
+# regression test for xowiki
+# $Id: test.tcl,v 1.9.2.2 2007/08/01 21:39:25 gustafn Exp $
+Object test
+test set passed 0
+test set failed 0
+test proc case msg {ad_return_top_of_page "$msg $msg "}
+test proc section msg {my reset; ns_write "$msg "}
+test proc subsection msg {ns_write "$msg "}
+test proc errmsg msg {ns_write "ERROR: $msg "; test incr failed}
+test proc okmsg msg {ns_write "OK: $msg "; test incr passed}
+test proc code msg {ns_write "$msg "}
+test proc hint msg {ns_write "$msg "}
+test proc reset {} {
+ array unset ::xotcl_cleanup
+ global af_parts af_key_name
+ array unset af_parts
+ array unset af_key_name
+}
+test proc without_ns_form {cmd} {
+ rename ::ns_queryget ::ns_queryget.orig
+ rename ::ns_querygetall ::ns_querygetall.orig
+ rename ::ad_returnredirect ::ad_returnredirect.orig
+ proc ::ns_queryget key {::xo::cc form_parameter $key ""}
+ proc ::ns_querygetall key {::xo::cc form_parameter $key {{}} }
+ proc ::ad_returnredirect url {::xo::cc returnredirect $url}
+ if {[catch {set r [uplevel $cmd]} errmsg]} {
+ if {$errmsg ne ""} {test code "error in command: $errmsg [info exists r]"}
+ set r ""
+ }
+ rename ::ns_queryget ""
+ rename ::ns_queryget.orig ::ns_queryget
+ rename ::ns_querygetall ""
+ rename ::ns_querygetall.orig ::ns_querygetall
+ rename ::ad_returnredirect ""
+ rename ::ad_returnredirect.orig ::ad_returnredirect
+ return $r
+}
+
+
+proc ? {cmd expected {msg ""}} {
+ set r [uplevel $cmd]
+ if {$msg eq ""} {set msg $cmd}
+ if {$r ne $expected} {
+ test errmsg "$msg returned '$r' ne '$expected'"
+ } else {
+ test okmsg "$msg - passed ([t1 diff] ms)"
+ }
+}
+
+set instance_name XOWIKI-TEST
+set index_vuh_parms {
+ {-m view}
+ {-folder_id:integer 0}
+}
+::xo::Timestamp t1
+
+test case "XoWiki Test Cases"
+
+test section "Basic Setup"
+
+test hint "Using XOTcl $::xotcl::version$::xotcl::patchlevel"
+? {expr {$::xotcl::version < 1.4}} 0 "XOTcl Version $::xotcl::version >= 1.4"
+
+set ns_cache_version_old [catch {ns_cache names xowiki_cache xxx}]
+if {$ns_cache_version_old} {
+ ? {set x old} new "upgrade ns_cache: cvs -z3 -d:pserver:anonymous@aolserver.cvs.sourceforge.net:/cvsroot/aolserver co nscache"
+} else {
+ ? {set x new} new "ns_cache version seems up to date"
+}
+
+set tdom_version [package require tdom]
+if {$tdom_version < "0.8.0"} {
+ ? {set x old} new "xowiki requires at least tdom 0.8.0 (released Aug 2004), \
+ the installed tdom version is to old ($tdom_version). \
+ Please Upgrade tdom from: cvs -z3 -d:pserver:anonymous@cvs.tdom.org:/usr/local/pubcvs co tdom
"
+} else {
+ ? {set x new} new "tdom version $tdom_version is ok"
+}
+########################################################################
+test section "Create New Package Instance of XoWiki"
+#
+# create a fresh instance for testing
+#
+if {[site_node::exists_p -url /$instance_name]} {
+ # we have already an instance, get rid of it
+ array set info [site_node::get_from_url -url /$instance_name -exact]
+ # is the instance mounted?
+ if {$info(package_id) ne ""} {
+ site_node::unmount -node_id $info(node_id)
+ }
+ site_node::delete -node_id $info(node_id)
+ #test code [array get info]
+}
+
+? {site_node::exists_p -url /$instance_name} 0 \
+ "the test instance does not exist"
+
+#set root_id [site_node::get_root_node_id]
+set root_id [db_string "" {select node_id from site_nodes where parent_id is null}]
+
+if {[db_0or1row check_broken_site_nodes {
+ select node_id, name from site_nodes where name = :instance_name and parent_id = :root_id
+}]} {
+ test hint "... site nodes seem broken, since we have an entry, but site_node::exists_p returns false"
+ test hint "... try to fix anyhow"
+ db_dml fix_broken_entry {
+ delete from site_nodes where name = :instance_name and parent_id = :root_id
+ }
+}
+
+# create a fresh instance
+array set node [site_node::get -url /]
+site_node::instantiate_and_mount \
+ -parent_node_id $node(node_id) \
+ -node_name $instance_name \
+ -package_name xowiki \
+ -package_key xowiki
+#test code [array get node]
+
+? {site_node::exists_p -url /$instance_name} 1 \
+ "created test instance /$instance_name"
+array set info [site_node::get_from_url -url /$instance_name -exact]
+? {expr {$info(package_id) ne ""}} 1 "package is mounted, package_id provided"
+
+
+test subsection "Basic Setup: Package, url= /$instance_name/"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/ \
+ -actual_query "" \
+ -user_id 0
+
+? {info exists package_id} 1 "package_id is exported"
+? {set package_id} $info(package_id) "package_id right value"
+? {::xotcl::Object isobject ::$package_id} 1 "we have a package_id object"
+? {$package_id package_url} /$instance_name/ "package_url"
+? {$package_id url} /$instance_name/
+? {$package_id id} $package_id "the id of the package object = package_id"
+
+test code [$package_id serialize]
+
+test subsection "Basic Setup: Folder Object"
+? {$package_id exists folder_id} 1 "folder_id is set"
+set folder_id [::$package_id folder_id]
+? {::xotcl::Object isobject ::$folder_id} 1 "we have a folder object"
+? {::xotcl::Object isobject ::${folder_id}::payload} 1 "we have a payload"
+? {::$folder_id name} ::$folder_id "name of folder object is ::folder_id"
+? {::$folder_id parent_id} $folder_id "parent_id of folder object is folder_id"
+? {expr {[::$folder_id item_id]>0}} 1 "item_id given"
+? {expr {[::$folder_id revision_id]>0}} 1 "revision_id given"
+? {db_string count "select count(*) from cr_items where parent_id = $folder_id"} 1 \
+ "folder contains the folder object"
+
+test subsection "Create and Render Index Page"
+? {$package_id set object} "" "object name parsed"
+? {set m} view "method passed from package initialize"
+set object [$package_id set object]
+set page_item_id [$package_id resolve_page $object $m]
+? {expr {$page_item_id ne ""}} 1 "index page resolved"
+? {::xotcl::Object isobject ::$page_item_id} 1 "we have a page object"
+? {expr {[::$page_item_id item_id]>0}} 1 "item_id given"
+? {expr {[::$page_item_id revision_id]>0}} 1 "revision_id given"
+? {::$page_item_id parent_id} $folder_id "parent_id of page object is folder_id"
+? {::$page_item_id package_id} $package_id "package_id of page object"
+? {::$page_item_id name} en:index "name of resolved index page"
+? {::$page_item_id istype ::xowiki::Page} 1 "type or subtype of ::xowiki::Page"
+
+set content [$package_id call $page_item_id $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+? {db_string count "select count(*) from cr_items where parent_id = $folder_id"} 2 \
+ "folder contains the folder object and the index page"
+#test code [$page_item_id serialize]
+
+test subsection "Check Permissions based on default policy"
+? {::xo::cc user_id} 0 "user_id is guest"
+? {::$package_id make_link ::$page_item_id delete return_url} "" \
+ "the public cannot delete this page"
+? {::$package_id make_link -privilege admin -link admin/ $package_id {} {}} "" \
+ "the public cannot admin this package"
+
+########################################################################
+#
+# run a new query, use en/index explicitely
+#
+test section "New Query: /$instance_name/en/index"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/index \
+ -actual_query "" \
+ -user_id 0
+
+? {info exists package_id} 1 "package_id is exported"
+? {set package_id} $info(package_id) "package_id right value"
+? {::xotcl::Object isobject ::$package_id} 1 "we have a package_id object"
+? {$package_id package_url} /$instance_name/ "package_url"
+? {$package_id url} /$instance_name/en/index "url"
+? {$package_id id} $package_id "the id of the package object = package_id"
+set object [::$package_id set object]
+set page_item_id [::$package_id resolve_page $object $m]
+set folder_id [::$package_id folder_id]
+? {::$page_item_id parent_id} $folder_id "parent_id of page object is folder_id"
+? {::$page_item_id package_id} $package_id "package_id of page object"
+? {::$page_item_id name} en:index "name of resolved index page"
+
+########################################################################
+#
+# run a new query
+#
+test section "New Query: /$instance_name/"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/ \
+ -actual_query "" \
+ -user_id 0
+
+? {info exists package_id} 1 "package_id is exported"
+? {set package_id} $info(package_id) "package_id right value"
+? {::xotcl::Object isobject ::$package_id} 1 "we have a package_id object"
+? {$package_id package_url} /$instance_name/ "package_url"
+? {$package_id url} /$instance_name/ "url"
+? {$package_id id} $package_id "the id of the package object = package_id"
+
+test subsection "Basic Setup: Folder Object (2nd)"
+? {$package_id exists folder_id} 1 "folder_id is set"
+set folder_id [::$package_id folder_id]
+? {::xotcl::Object isobject ::$folder_id} 1 "we have a folder object"
+? {::xotcl::Object isobject ::${folder_id}::payload} 1 "we have a payload"
+? {::$folder_id name} ::$folder_id "name of folder object is ::folder_id"
+? {::$folder_id parent_id} $folder_id "parent_id of folder object is folder_id"
+? {expr {[::$folder_id item_id]>0}} 1 "item_id given"
+? {expr {[::$folder_id revision_id]>0}} 1 "revision_id given"
+? {db_string count "select count(*) from cr_items where parent_id = $folder_id"} 2 \
+ "folder contains the folder object and index"
+
+test subsection "Render Index Page (2nd)"
+? {$package_id set object} "" "object name parsed"
+? {set m} view "method passed from package initialize"
+set object [$package_id set object]
+set page_item_id [$package_id resolve_page $object $m]
+? {expr {$page_item_id ne ""}} 1 "index page resolved"
+? {::xotcl::Object isobject ::$page_item_id} 1 "we have a page object"
+? {expr {[::$page_item_id item_id]>0}} 1 "item_id given"
+? {expr {[::$page_item_id revision_id]>0}} 1 "revision_id given"
+? {::$page_item_id parent_id} $folder_id "parent_id of page object is folder_id"
+? {::$page_item_id package_id} $package_id "package_id of page object"
+? {::$page_item_id name} en:index "name of resolved index page"
+? {::$page_item_id istype ::xowiki::Page} 1 "type or subtype of ::xowiki::Page"
+
+set content [$package_id call $page_item_id $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+#test code [$page_item_id serialize]
+
+########################################################################
+#
+# run a new query
+#
+test section "New Query: /$instance_name/weblog"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/weblog \
+ -actual_query "" \
+ -user_id 0
+
+? {$package_id package_url} /$instance_name/ "package_url"
+? {$package_id url} /$instance_name/weblog "url"
+? {$package_id id} $package_id "the id of the package object = package_id"
+set folder_id [::$package_id folder_id]
+
+test subsection "Create and Render Weblog"
+set content [::$package_id invoke -method $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+
+? {db_string count "select count(*) from cr_items where parent_id = $folder_id"} 5 \
+ "folder contains: folder object, index and weblog page (+2 includelets)"
+
+
+
+########################################################################
+test section "New Query: /$instance_name/en/weblog"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/weblog \
+ -actual_query "" \
+ -user_id 0
+
+set content [::$package_id invoke -method $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+
+set full_weblog_content_length $content_length
+
+
+########################################################################
+test section "New Query: /$instance_name/en/weblog with summary=1"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/weblog \
+ -actual_query "summary=1" \
+ -user_id 0
+
+set content [::$package_id invoke -method $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+? {expr {$full_weblog_content_length > $content_length}} 1 "summary is shorter"
+
+
+########################################################################
+test section "Testing as SWA: query /$instance_name/ "
+
+set swas [db_list get_swa "select grantee_id from acs_permissions \
+ where object_id = -4 and privilege = 'admin'"]
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/ \
+ -actual_query "" \
+ -user_id [lindex $swas 0]
+
+set content [::$package_id invoke -method $m]
+? {string first Error $content} -1 "page contains no error"
+
+test subsection "Check Permissions based on default policy"
+? {expr {[::xo::cc user_id] != 0}} 1 "user_id [lindex $swas 0] is not guest"
+? {expr {[::$package_id make_link ::$page_item_id delete return_url] ne ""}} 1 \
+ "SWA sees the delete link"
+? {expr {[::$package_id make_link -privilege admin -link admin/ $package_id {} {}] ne ""}} 1 \
+ "SWA sees admin link"
+? {db_string count "select count(*) from cr_items where parent_id=[$package_id folder_id]"} 5 \
+ "folder contains: folder object, index and weblog page (+2 includelets)"
+
+
+########################################################################
+test section "Delete weblog-portlet via weblink"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/weblog-portlet \
+ -actual_query "m=delete" \
+ -user_id [lindex $swas 0]
+
+set content [::$package_id invoke -method $m]
+? {string first Error $content} -1 "page contains no error"
+? {::xo::cc exists __continuation} 1 "continuation exists"
+? {::xo::cc set __continuation} "ad_returnredirect /$instance_name/" \
+ "redirect to main instance"
+? {db_string count "select count(*) from cr_items where parent_id=[$package_id folder_id]"} 4 \
+ "folder contains: folder object, index and weblog page (+1 includelet)"
+
+test subsection "Create a test page named hello"
+
+set page [::xowiki::Page new \
+ -title "Hello World" \
+ -name en:hello \
+ -package_id $package_id \
+ -parent_id [$package_id folder_id] \
+ -destroy_on_cleanup \
+ -text {
+ Hello [[Wiki]] World.
+ }]
+$page set_content [string trim [$page text] " \n"]
+$page initialize_loaded_object
+$page save_new
+? {db_string count "select count(*) from cr_items where parent_id=[$package_id folder_id]"} 5 \
+ "folder contains: folder object, index and weblog, hello page (+1 includelet)"
+? {expr {[$page revision_id]>0}} 1 "revision_id given"
+? {expr {[$page item_id]>0}} 1 "item_id given"
+set revision_id1 [$page revision_id]
+set item_id1 [$page item_id]
+
+$page append title "- V.2"
+$page save
+? {db_string count "select count(*) from cr_items where parent_id=[$package_id folder_id]"} 5 \
+ "still 5 pages"
+? {expr {[$page revision_id]>$revision_id1}} 1 "revision_id > old revision_id"
+? {expr {[$page item_id] == $item_id1}} 1 "item id the same"
+
+
+
+########################################################################
+test section "Recreate weblog-portlet"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/weblog \
+ -actual_query "summary=1" \
+ -user_id 0
+
+set content [::$package_id invoke -method $m]
+set content_length [string length $content]
+? {expr {$content_length > 1000}} 1 \
+ "page rendered, content-length $content_length > 1000"
+? {string first Error $content} -1 "page contains no error"
+? {db_string count "select count(*) from cr_items where parent_id=[$package_id folder_id]"} 6 \
+ "again, 6 pages"
+
+
+########################################################################
+test section "Query revisions for hello page via weblink"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/hello \
+ -actual_query "m=revisions" \
+ -user_id [lindex $swas 0]
+
+set content [::$package_id invoke -method $m]
+? {string first Error $content} -1 "page contains no error"
+? {expr {[string first 2: $content]>-1}} 1 "page contains two revisions"
+
+
+########################################################################
+test section "Edit hello page via weblink"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/hello \
+ -actual_query "m=edit" \
+ -user_id [lindex $swas 0]
+
+set content [::$package_id invoke -method $m]
+? {string first Error $content} -1 "page contains no error"
+? {expr {[string first "- V.2" $content]>-1}} 1 \
+ "form page contains the modified title"
+
+regexp {name="item_id" value="([^\"]+)"} $content _ returned_item_id
+? {info exists returned_item_id} 1 "item_id contained in form"
+? {expr {$returned_item_id > 0}} 1 "item_id $returned_item_id > 0"
+? {$package_id isobject $returned_item_id} 1 "item is instantiated"
+
+regexp {name="folder_id" value="([^\"]+)"} $content _ returned_folder_id
+? {info exists returned_folder_id} 1 "folder_id contained in form"
+? {expr {$returned_folder_id > 0}} 1 "returned folder id $returned_folder_id >0"
+
+regexp {name="__key_signature" value="([^\"]+)"} $content _ signature
+? {info exists signature} 1 "signature contained in form"
+? {expr {$signature ne ""}} 1 "signature not empty"
+
+set title [$returned_item_id title]
+set text [lindex [$returned_item_id text] 0]
+
+########################################################################
+test section "Submit edited hello page via weblink"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/hello \
+ -actual_query "m=edit" \
+ -user_id [lindex $swas 0] \
+ -form_parameter [subst {
+ form:id f1
+ form:mode edit
+ formbutton:ok { OK }
+ __refreshing_p 0
+ __confirmed_p 0
+ __new_p 0
+ __key_signature {$signature}
+ __object_name en:hello
+ name en:hello
+ object_type ::xowiki::Page
+ text.format text/html
+ creator {Gustaf Neumann}
+ description {{this is the description}}
+ text {$text ... just testing .. }
+ nls_language en_US
+ folder_id $returned_folder_id
+ title {$title}
+ item_id $returned_item_id }]
+
+set content [test without_ns_form {::$package_id invoke -method $m}]
+? {string first Error $content} -1 "page contains no error"
+
+? {::xo::cc exists __continuation} 1 "continuation exists"
+? {::xo::cc set __continuation} "ad_returnredirect /$instance_name/hello" \
+ "redirect to hello page"
+
+########################################################################
+test section "Query revisions for hello page via weblink"
+
+::xowiki::Package initialize -parameter $index_vuh_parms \
+ -package_id $info(package_id) \
+ -url /$instance_name/en/hello \
+ -actual_query "m=revisions" \
+ -user_id [lindex $swas 0]
+
+set content [::$package_id invoke -method $m]
+? {string first Error $content} -1 "page contains no error"
+? {expr {[string first 3: $content]>-1}} 1 "page contains three revisions"
+
+
+ns_write "
+
+ Tests passed: [test set passed]
+ Tests failed: [test set failed]
+ Tests Time: [t1 diff -start]ms
+"
\ No newline at end of file
Index: openacs-4/packages/xowiki/www/admin/samples/ajax-chat.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/admin/samples/ajax-chat.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/admin/samples/ajax-chat.tcl 1 Aug 2007 21:39:25 -0000 1.4.2.2
@@ -0,0 +1,21 @@
+namespace eval ::xowiki::tmp {
+ ::xowiki::Object create ajax-chat -noinit \
+ -set object_type ::xowiki::Object \
+ -set lang en \
+ -set description {} \
+ -set text {
+ proc content {} {
+ ::xowiki::Chat login -chat_id 22
+ }
+ } \
+ -set nls_language en_US \
+ -set mime_type {text/html} \
+ -set name en:ajax-chat \
+ -set title en:ajax-chat
+}
+
+set title "Import XoWiki Pages"
+set context {}
+set msg [::xowiki::Page import -objects ::xowiki::tmp::ajax-chat -replace true]
+template::set_file "[file dir $__adp_stub]/../importmsg"
+ad_return_template
Index: openacs-4/packages/xowiki/www/ajax/chat.js
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/chat.js,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/ajax/chat.js 1 Aug 2007 21:39:26 -0000 1.4.2.2
@@ -0,0 +1,78 @@
+// simple javascript support for polling ajax based chat interface
+// $Id: chat.js,v 1.4.2.2 2007/08/01 21:39:26 gustafn Exp $
+// -gustaf neumann April 2006
+
+function receiver1() {
+ if (http.readyState == 4) {
+ // alert('status code =' + http.status);
+ if (http.status != 200) {
+ alert('Something wrong in HTTP request, status code = ' + http.status);
+ }
+ }
+}
+
+function chatReceiver() {
+ if (http.readyState == 4) {
+ // alert('status code =' + http.status);
+ if (http.status == 200) {
+ appendToMessages(http.responseText);
+ } else {
+ clearInterval();
+ alert('Something wrong in HTTP request, status code = ' + http.status);
+ }
+ }
+}
+
+function appendToMessages(content) {
+ var xmlobject = (new DOMParser()).parseFromString(content, 'application/xhtml+xml');
+ var items = xmlobject.getElementsByTagName('TR');
+ //alert('found ' + items.length + ' items');
+ //var counter = document.getElementById('chatCounter');
+ //counter.innerHTML = parseInt(counter.innerHTML) + 1;
+ //document.getElementById('chatResponse').innerHTML = 'items = ' + items.length + ' l=' + content.length + ' ' + escape(content);
+
+ //if (items.length > 0) {alert('appending ' + content);}
+ var doc = frames['ichat'].document;
+ var tbody = frames['ichat'].document.getElementById('messages').tBodies[0];
+ //var tbody = tbodies[tbodies.length -1];
+ //for (var i = 0 ; i < items.length ; i++) {
+ // tbody.appendChild(frames['ichat'].document.importNode(items[i],true));
+ //}
+ var tr, td, e, s;
+ for (var i = 0 ; i < items.length ; i++) {
+ tr = doc.createElement('tr');
+ e = items[i].getElementsByTagName('TD');
+ td = doc.createElement('td');
+ td.innerHTML = decodeURIComponent(e[0].firstChild.nodeValue);
+ td.className = 'timestamp';
+ tr.appendChild(td);
+
+ td = doc.createElement('td');
+ s = e[1].firstChild.nodeValue;
+ td.innerHTML = decodeURIComponent(e[1].firstChild.nodeValue.replace(/\+/g,' '));
+ td.className = 'user';
+ tr.appendChild(td);
+
+ td = doc.createElement('td');
+ td.innerHTML = decodeURIComponent(e[2].firstChild.nodeValue.replace(/\+/g,' '));
+ td.className = 'message';
+ tr.appendChild(td);
+
+ tbody.appendChild(tr);
+ }
+ frames['ichat'].window.scrollTo(0,tbody.offsetHeight);
+}
+
+
+function chatSendMsg(send_url,handler) {
+ var msgField = document.getElementById('chatMsg');
+ chatSendCmd(send_url + encodeURIComponent(msgField.value),handler);
+ msgField.value = '';
+}
+
+var msgcount = 0; // hack to overcome IE
+function chatSendCmd(url,handler) {
+ http.open('GET', url + '&mc=' + msgcount++, true);
+ http.onreadystatechange = handler;
+ http.send(null);
+}
Index: openacs-4/packages/xowiki/www/ajax/chat.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/chat.tcl,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/ajax/chat.tcl 1 Aug 2007 21:39:26 -0000 1.4.2.2
@@ -0,0 +1,40 @@
+ad_page_contract {
+ a tiny chat client
+
+ @author Gustaf Neumann (gustaf.neumann@wu-wien.ac.at)
+ @creation-date Jan 31, 2006
+ @cvs-id $Id: chat.tcl,v 1.4.2.2 2007/08/01 21:39:26 gustafn Exp $
+} -query {
+ m
+ id
+ s
+ msg:optional
+ {mode ""}
+}
+
+#ns_log notice "--c m=$m session_id=$s [clock format [lindex [split $s .] 1] -format %H:%M:%S] mode=$mode"
+::xowiki::Chat c1 -volatile -chat_id $id -session_id $s -mode $mode
+switch -- $m {
+ add_msg {
+ #ns_log notice "--c call c1 $m '$msg'"
+ set _ [c1 $m $msg]
+ #ns_log notice "--c add_msg returns '$_'"
+ }
+ login -
+ subscribe -
+ get_new -
+ get_all {set _ [c1 $m]}
+ default {ns_log error "--c unknown method $m called."}
+}
+
+ns_return 200 text/html "
+
+
+
+
+
+"
\ No newline at end of file
Index: openacs-4/packages/xowiki/www/ajax/scripted-streaming-chat.js
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/www/ajax/Attic/scripted-streaming-chat.js,v
diff -u -N
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/xowiki/www/ajax/scripted-streaming-chat.js 1 Aug 2007 21:39:26 -0000 1.1.2.2
@@ -0,0 +1,73 @@
+// simple javascript support for streaming ajax based chat interface
+// $Id: scripted-streaming-chat.js,v 1.1.2.2 2007/08/01 21:39:26 gustafn Exp $
+// -gustaf neumann April 2006
+
+function getHttpObject() {
+ var http_request = false;
+ if (window.XMLHttpRequest) { // Mozilla, Safari,...
+ http_request = new XMLHttpRequest();
+ } else if (window.ActiveXObject) { // IE
+ try {
+ http_request = new ActiveXObject('Msxml2.XMLHTTP');
+ } catch (e) {
+ try {
+ http_request = new ActiveXObject('Microsoft.XMLHTTP');
+ } catch (e) {}
+ }
+ }
+
+ if (!http_request) {
+ alert('Cannot create and instance of XMLHTTP');
+ }
+ return http_request;
+}
+
+function getData(data) {
+ var messages = document.getElementById('messages');
+ for (var i=0;ixowiki-doc
+
+
+ Last modified: Mon Oct 31 13:36:50 CET 2005
+