Index: openacs-4/packages/forums/tcl/messages-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/forums/tcl/messages-procs.tcl,v diff -u -r1.59 -r1.60 --- openacs-4/packages/forums/tcl/messages-procs.tcl 23 Oct 2018 20:18:41 -0000 1.59 +++ openacs-4/packages/forums/tcl/messages-procs.tcl 3 Sep 2024 15:37:38 -0000 1.60 @@ -44,18 +44,16 @@ set message_id [package_instantiate_object -var_list $var_list forums_message] - get -message_id $message_id -array message - if {[info exists message(state)] && $message(state) eq "approved"} { - do_notifications -message_id $message_id -user_id $user_id - } + forum::message::do_notifications \ + -message_id $message_id -user_id $user_id } on_error { db_abort_transaction # Check to see if the message with a message_id matching the # message_id argument was in the database before calling - # this procedure. If so, the error is due to a double click + # this procedure. If so, the error is due to a double click # and we should continue without returning an error. if {$original_message_id ne ""} { @@ -73,7 +71,7 @@ } forum::flush_cache \ - -forum_id $forum_id + -forum_id $forum_id return $message_id } @@ -94,61 +92,90 @@ set url [lindex [site_node::get_url_from_object_id -object_id $package_id] 0] set url [ad_url]$url - set useScreenNameP [parameter::get -parameter "UseScreenNameP" -default 0] - if {$useScreenNameP eq 0 && $user_id ne 0} { - if { $user_id eq "" } { - set user_id $message(user_id) - } - } else { - set user_id [party::get_by_email \ - -email [ad_host_administrator]] + set message_url ${url}message-view?message_id=$message(root_message_id) + set forum_url ${url}forum-view?forum_id=$message(forum_id) + + if {$message(state) eq "approved"} { + forum::message::notify_users \ + -message_array message \ + -forum_url $forum_url \ + -message_url $message_url } - set notif_user $user_id + forum::message::notify_moderators \ + -message_array message \ + -forum_url $forum_url \ + -message_url $message_url + + # This computations are not used... just commented for now. + # if {$useScreenNameP eq 0 && $user_id ne 0} { + # if { $user_id eq "" } { + # set user_id $message(user_id) + # } + # } else { + # set user_id [party::get_by_email \ + # -email [ad_host_administrator]] + # } + # set notif_user $user_id +} + +ad_proc -private forum::message::notify_users { + -message_array:required + -forum_url:required + -message_url:required +} { + Notify users of a new approved forum message. + + @param message_array name of message array of forum info in the caller scope +} { + upvar 1 $message_array message + + set useScreenNameP [parameter::get -parameter "UseScreenNameP" -default 0] + set attachments [attachments::get_attachments -object_id $message(message_id)] set message_text [ad_html_text_convert -from $message(format) -to text/plain -- $message(content)] set message_html [ad_html_text_convert -from $message(format) -to text/html -- $message(content)] set SecureOutboundP [parameter::get -parameter "SecureOutboundP" -default 0] if { $SecureOutboundP && [ns_conn isconnected] && [security::secure_conn_p] } { - set href ${url}message-view?message_id=$message(root_message_id) - set message_html "

#forums.Message_content_withheld# #forums.To_view_message_follow_link# [ns_quotehtml $href]

" + set href [ns_quotehtml $message_url] + set message_html "

#forums.Message_content_withheld# #forums.To_view_message_follow_link# $href

" set message_text [ad_html_text_convert -from text/html -to text/plain -- $message_html] + } else { + # + # The resulting HTML messages is sent in total by + # notifications::send through [lang::util::localize...]. In case + # a forums message contains something looking like a localized + # message key, it will be substituted. One rough attempt is to add + # a zero width space after the "#" signs to make the regular + # expression searching for the message keys fail.... + # + regsub -all -- "#" $message_html "#\\​" message_html } set html_version "" - append html_version "#forums.Forum#: $message(forum_name)
\n" - append html_version "#forums.Thread#: $message(root_subject)
\n" + append html_version "#forums.Forum#: $message(forum_name)
\n" + append html_version "#forums.Thread#: $message(root_subject)
\n" if {$useScreenNameP == 0} { append html_version "#forums.Author#: $message(user_name)
\n" } else { append html_version "#forums.Author#: $message(screen_name)
\n" } append html_version "#forums.Posted#: $message(posting_date)
" append html_version "\n
\n" - # - # The resulting HTML messages is sent in total by - # notifications::send through [lang::util::localize...]. In case - # a forums message contains something looking like a localized - # message key, it will be substituted. One rough attempt is to add - # a zero width space after the "#" signs to make the regular - # expression searching for the message keys fail.... - # - regsub -all "#" $message_html "#\\​" message_html - + append html_version $message_html append html_version "

" if {[llength $attachments] > 0} { - append html_version "#forums.Attachments#: + append html_version "#forums.Attachments#:

" - + foreach attachment $attachments { + append html_version "
  • [lindex $attachment 1]
  • " + } + append html_version "" } set html_version $html_version @@ -158,20 +185,20 @@ #forums.Forum#: $message(forum_name) #forums.Thread#: $message(root_subject)\n" if {$useScreenNameP == 0} { - append text_version "#forums.Author#: $message(user_name)" + append text_version "#forums.Author#: $message(user_name)" } else { - append text_version "#forums.Author#: $message(screen_name)" + append text_version "#forums.Author#: $message(screen_name)" } append text_version " #forums.Posted#: $message(posting_date) ----------------------------------------- $message_text ----------------------------------------- -#forums.To_post_a_reply_to_this_email_or_view_this_message_go_to# -${url}message-view?message_id=$message(root_message_id) +#forums.To_view_message_follow_link# +$message_url #forums.To_view_Forum_forum_name_go_to# -${url}forum-view?forum_id=$message(forum_id) +$forum_url " # Do the notification for the forum notification::new \ @@ -183,7 +210,7 @@ -notif_text $text_version \ -notif_html $html_version - + # Eventually we need notification for the root message too notification::new \ -type_id [notification::type::get_type_id \ @@ -194,7 +221,81 @@ -notif_text $text_version \ -notif_html $html_version } - + +ad_proc -private forum::message::notify_moderators { + -message_array:required + -forum_url:required + -message_url:required +} { + Notify moderators of a new forum message + + @param message_array name of message array of forum info in the caller scope +} { + upvar 1 $message_array message + + set useScreenNameP [parameter::get -parameter "UseScreenNameP" -default 0] + + # Moderated messages are never notified in full, as they might + # contain unsuitable content by definition. + set href [ns_quotehtml $message_url] + set message_html "

    #forums.Message_content_withheld# #forums.To_view_message_follow_link# $href

    " + set message_text [ad_html_text_convert -from text/html -to text/plain -- $message_html] + + set html_version "" + append html_version "#forums.Forum#: $message(forum_name)
    \n" + append html_version "#forums.Thread#: $message(root_subject)
    \n" + if {$useScreenNameP == 0} { + append html_version "#forums.Author#: $message(user_name)
    \n" + } else { + append html_version "#forums.Author#: $message(screen_name)
    \n" + } + append html_version "#forums.Posted#: $message(posting_date)
    " + append html_version "\n
    \n" + + append html_version $message_html + append html_version "

    " + + set text_version "" + append text_version " +#forums.Forum#: $message(forum_name) +#forums.Thread#: $message(root_subject)\n" + if {$useScreenNameP == 0} { + append text_version "#forums.Author#: $message(user_name)" + } else { + append text_version "#forums.Author#: $message(screen_name)" + } + append text_version " +#forums.Posted#: $message(posting_date) +----------------------------------------- +$message_text +----------------------------------------- +#forums.To_view_message_follow_link# +$message_url + +#forums.To_view_Forum_forum_name_go_to# +$forum_url +" + # Do the notification for the forum + notification::new \ + -type_id [notification::type::get_type_id \ + -short_name forums_forum_moderator_notif] \ + -object_id $message(forum_id) \ + -response_id $message(message_id) \ + -notif_subject "\[$message(forum_name)\] $message(subject) (#forums.moderated#)" \ + -notif_text $text_version \ + -notif_html $html_version + + # Eventually we need notification for the root message too + notification::new \ + -type_id [notification::type::get_type_id \ + -short_name forums_message_moderator_notif] \ + -object_id $message(root_message_id) \ + -response_id $message(message_id) \ + -notif_subject "\[$message(forum_name)\] $message(subject) (#forums.moderated#)" \ + -notif_text $text_version \ + -notif_html $html_version +} + ad_proc -public forum::message::edit { {-message_id:required} {-subject:required} @@ -210,7 +311,7 @@ db_dml update_message_title {} if {!$no_callback_p} { - callback forum::message_edit -package_id [ad_conn package_id] -message_id $message_id + callback forum::message_edit -package_id [ad_conn package_id] -message_id $message_id } } @@ -233,25 +334,51 @@ # Select the info into the upvar'ed Tcl Array upvar $array row - set query select_message + # make sure array is empty + array unset row - if {[ad_conn isconnected] && [forum::attachments_enabled_p]} { - set query select_message_with_attachment - } + set forum_id [::xo::dc list -prepare integer get_forum_id_from_message_id { + select forum_id from forums_messages where message_id = :message_id + }] + set attachments_sql [expr {[ns_conn isconnected] && [forum::attachments_enabled_p -forum_id $forum_id] ? { + (select count(*) from attachments + where object_id = m.message_id) as n_attachments, + } : ""}] - if {![db_0or1row $query {} -column_array row]} { - if {[array exists row]} { - array unset row - } - } else { + set sql [subst -nocommands { + with recursive message_hierarchy as ( + select 1 as level, message_id, parent_id + from forums_messages + where message_id = :message_id + + union all + + select h.level + 1, m.message_id, m.parent_id + from forums_messages m, + message_hierarchy h + where m.message_id = h.parent_id + ) + select m.*, + $attachments_sql + root.level as tree_level, + root.message_id as root_message_id, + (select subject from forums_messages + where message_id = root.message_id) as root_subject, + to_char(m.posting_date, 'YYYY-MM-DD HH24:MI:SS') as posting_date_ansi, + (select name from forums_forums + where forum_id = m.forum_id) as forum_name + from forums_messages m, + (select level, message_id + from message_hierarchy + where parent_id is null) as root + where m.message_id = :message_id + }] + if {[db_0or1row select_message $sql -column_array row]} { set user [acs_user::get -user_id $row(user_id)] set row(user_name) [dict get $user name] set row(user_email) [dict get $user email] set row(screen_name) [dict get $user screen_name] - - forum::get -forum_id $row(forum_id) -array forum - set row(forum_name) $forum(name) - + # Convert to user's date/time format set row(posting_date_ansi) [lc_time_system_to_conn $row(posting_date_ansi)] set row(posting_date_pretty) [lc_time_fmt $row(posting_date_ansi) "%x %X"] @@ -263,7 +390,7 @@ {-state:required} } { Set the new state for a message.
    - Usually used for approval. + Usually, used for approval. } { set var_list [list \ [list message_id $message_id] \ @@ -280,7 +407,7 @@ } { Reject a message. } { - set_state -message_id $message_id -state rejected + forum::message::set_state -message_id $message_id -state rejected } ad_proc -public forum::message::approve { @@ -289,8 +416,8 @@ Approve a message. } { db_transaction { - set_state -message_id $message_id -state approved - do_notifications -message_id $message_id + forum::message::set_state -message_id $message_id -state approved + forum::message::do_notifications -message_id $message_id } } @@ -301,20 +428,13 @@ Delete a message and obviously all of its descendents. } { db_transaction { - if {!$no_callback_p} { - callback forum::message_delete -package_id [ad_conn package_id] -message_id $message_id - } + if {!$no_callback_p} { + callback forum::message_delete -package_id [ad_conn package_id] -message_id $message_id + } forum::message::get -message_id $message_id -array msg set forum_id $msg(forum_id) - set is_root_p [expr {$msg(parent_id) eq ""}] - if { $is_root_p && [forum::use_ReadingInfo_p] } { - set db_antwort [db_string forums_reading_info__remove_msg { - select forums_reading_info__remove_msg (:message_id); - }] - } - # Remove the notifications notification::request::delete_all -object_id $message_id @@ -333,7 +453,26 @@ Close a thread.
    This is not exactly a cheap operation if the thread is long. } { - db_exec_plsql thread_close {} + db_dml close_thread { + update forums_messages set + open_p = 'f' + where message_id in ( + with recursive message_hierarchy as ( + select message_id + from forums_messages + where message_id = :message_id + + union all + + select m.message_id + from forums_messages m, + message_hierarchy h + where m.parent_id = h.message_id + ) + select message_id + from message_hierarchy + ) + } } ad_proc -public forum::message::open { @@ -342,38 +481,76 @@ Reopen a thread.
    This is not exactly a cheap operation if the thread is long. } { - db_exec_plsql thread_open {} + db_dml close_thread { + update forums_messages set + open_p = 't' + where message_id in ( + with recursive message_hierarchy as ( + select message_id + from forums_messages + where message_id = :message_id + + union all + + select m.message_id + from forums_messages m, + message_hierarchy h + where m.parent_id = h.message_id + ) + select message_id + from message_hierarchy + ) + } } -ad_proc -public forum::message::get_attachments { +ad_proc -deprecated forum::message::get_attachments { {-message_id:required} } { Get the attachments for a message. + + DEPRECATED: this proc requires a connection context in a forums + package instance to work as expected. An alternative could be to + retrieve the forum_id from the message instead, but as this proc + is not used anywhere and its logics are not difficult to inline, + we just deprecate it. + + @see forum::attachments_enabled_p + @see attachments::get_attachments } { # If attachments aren't enabled, then we stop - if {![forum::attachments_enabled_p]} { + set forum_id [::xo::dc list -prepare integer get_forum_id_from_message_id { + select forum_id from forums_messages where message_id = :message_id + }] + + if {![forum::attachments_enabled_p -forum_id $forum_id]} { return [list] } return [attachments::get_attachments -object_id $message_id] } -ad_proc -public forum::message::subject_sort_filter { +ad_proc -deprecated forum::message::subject_sort_filter { -forum_id:required -order_by:required } { @return A piece of HTML for toggling the sort order of threads (subjects) in a forum. The user can either sort by the first postings in subjects (the creation date of the subjects) or the last one. + DEPRECATED: this proc is not mentioned anywhere in current + upstream codebase. Furthermore, it refers to a very + specific UI (e.g. sorting properties, styling...) and + does therefore provide little value in general. + + @see idioms in the specific UI + @author Peter Marklund } { - set subject_label "[_ forums.lt_First_post_in_subject]" - set child_label "[_ forums.Last_post_in_subject]" - set new_order_by [ad_decode $order_by posting_date last_child_post posting_date] + set subject_label [_ forums.lt_First_post_in_subject] + set child_label [_ forums.Last_post_in_subject] + set new_order_by [expr {$order_by eq "posting_date" ? "last_child_post" : "posting_date"}] - set export_vars [export_vars -override [list [list order_by $new_order_by]] {order_by forum_id}] - set toggle_url "[ad_conn url]?${export_vars}" + set toggle_url [export_vars -base [ad_conn url] -override {{order_by $new_order_by}} {order_by forum_id}] if {$order_by eq "posting_date"} { # subject selected set subject_link "$subject_label" @@ -388,18 +565,25 @@ return $sort_filter } -ad_proc -public forum::message::initial_message { +ad_proc -deprecated forum::message::initial_message { {-forum_id {}} {-parent {}} {-message:required} } { Create an array with values initialized for a new message. + + DEPRECATED: this proc is not used in current upstream code, its + upvar juggling is questionable and most of the data + returned is already provided from the start. + + @see direct idioms on the API used in here + @see forum::format::reply_subject } { upvar $message init_msg if { $forum_id eq "" && $parent eq "" } { return -code error [_ forums.lt_You_either_have_to] - } + } if { $parent ne "" } { upvar $parent parent_msg