%3 ::xo::Package ::xo::Package exists_form_parameter exists_query_parameter form_parameter get_parameter handle_http_caching init initialize insert instantiate_forms process_init_parameter query_parameter reply_to_user require_root_folder return_page returnredirect set_url update ::xo::db::Object ::xo::db::Object ::xo::Package->::xo::db::Object ::xo::db::chat_transcript ::xo::db::chat_transcript insert save_new update ::xo::db::chat_transcript->::xo::db::Object ::xo::db::chat_room ::xo::db::chat_room ban_user count_messages create_transcript delete delete_messages flush grant_creator grant_moderator grant_user insert post_message revoke_moderator revoke_user save_new transcript_messages unban_user update ::xo::db::chat_room->::xo::db::Object ::xo::db::CrItem ::xo::db::CrItem changed_redirect_url current_user_id delete fix_content initialize_loaded_object is_cached_object is_package_root_folder privilege=creator rename save save_new set_live_revision update update_attribute_from_slot update_content update_item_index update_revision www-revisions ::xo::db::CrCache::Item ::xo::db::CrCache::Item delete flush_from_cache_and_refresh remove_non_persistent_vars rename save save_new set_non_persistent_vars update_attribute_from_slot ::xo::db::CrItem->::xo::db::CrCache::Item instmixin ::xo::db::CrItem->::xo::db::Object ::xo::db::apm_parameter ::xo::db::apm_parameter insert update ::xo::db::apm_parameter->::xo::db::Object ::xo::parameter ::xo::parameter ::xo::db::apm_parameter->::xo::parameter instmixin ::xotcl::Object ::xotcl::Object ::xo::db::CrCache::Item->::xotcl::Object ::xo::oauth::ServerMetadata ::xo::oauth::ServerMetadata update ::xo::oauth::ServerMetadata->::xo::db::CrItem ::xo::db::image ::xo::db::image update ::xo::db::image->::xo::db::CrItem ::xo::oauth::ClientMetadata ::xo::oauth::ClientMetadata ::xo::oauth::ClientMetadata->::xo::db::CrItem ::xowiki::Page ::xowiki::Page → container_already_rendered → find_slot → get_tags → import → quoted_html_content → save_tags __debug_known_field_names add_computed_instance_attributes adp_subst anchor anchor_parent_id build_instance_attribute_map build_name can_be_linked can_contain can_link can_save category_export category_import changed_redirect_url check_adp_include_path check_unresolved_references condition=is_folder_page condition=match condition=regexp content_header_append content_header_get copy_content_vars create_form_field create_form_fields create_form_fields_from_form_constraints create_form_page_instance create_link create_raw_form_field css_class_name default_instance_attributes demarshall detail_link div edit_set_default_values edit_set_file_selector_folder error_during_render error_in_includelet evaluate_form_field_condition exists_form_parameter exists_query_parameter field_names find_slot footer form_field_exists form_field_flush_cache form_field_index form_parameter get_anchor_and_query get_content get_description get_folder get_form_data get_html_from_content get_ids_for_bulk_actions get_instance_attributes get_nls_language_from_lang get_parent_object get_property_from_link_page get_query_parameter_return_url get_rich_text_spec get_target_from_link_page htmlFooter include include_content initialize_loaded_object instantiate_includelet is_folder_page is_form is_link_page is_new_entry is_unprefixed item_ref lang lookup_cached_form_field lookup_form_field map_categories map_party marshall mutual_overwrite_occurred new_link normalize_internal_link_name notification_detail_link notification_notify notification_render notification_subject physical_item_id physical_package_id physical_parent_id pretty_link pretty_name query_parameter record_last_visited references references_update regsub_eval rename render render_content render_icon render_includelet reset_resolve_context resolve_included_page_name return_redirect_without_params reverse_map_party reverse_map_party_attribute save save_data save_new search_render self_link_ids serialize_relocatable set_content set_resolve_context show_fields stats_record_count stats_record_detail substitute_markup translate unescape unset_temporary_instance_variables update update_publish_status validate=form_constraints validate=form_input_fields validate=name validate=page_order www-autosave-attribute www-bulk-delete www-clipboard-add www-clipboard-clear www-clipboard-content www-clipboard-copy www-clipboard-export www-create-new www-create-or-use www-csv-dump www-delete www-delete-revision www-diff www-duplicate www-edit www-list www-make-live-revision www-popular-tags www-revisions www-save-attributes www-save-tags www-toggle-publish-status www-validate-attribute www-view ::xowiki::Page->::xo::db::CrItem ::xo::db::CrFolder ::xo::db::CrFolder → delete → fetch_object → get_instance_from_db → instance_select_query → register_content_types delete save save_new update ::xo::db::CrFolder->::xo::db::CrItem ::xo::oauth::Credentials ::xo::oauth::Credentials as_encoded_string update ::xo::oauth::Credentials->::xo::db::CrItem ::xowiki::File ::xowiki::File build_name demarshall full_file_name html_content marshall pretty_name render_content render_icon search_render www-download ::xowiki::File->::xowiki::Page ::xowiki::PageTemplate ::xowiki::PageTemplate → count_usages count_usages update www-delete ::xowiki::PageTemplate->::xowiki::Page ::xowiki::PageInstance ::xowiki::PageInstance → get_list_from_form_constraints → get_short_spec_from_form_constraints adp_subst count_usages create_raw_form_field demarshall field_names_from_form_constraints get_field_label get_field_type get_form get_form_constraints get_from_template get_short_spec get_template_object render_content template_vars update widget_spec_from_folder_object www-use-template ::xowiki::PageInstance->::xowiki::Page ::xowiki::PlainPage ::xowiki::PlainPage render_content set_content substitute_markup unescape ::xowiki::PlainPage->::xowiki::Page ::xo::oauth::TempCredentials ::xo::oauth::TempCredentials update ::xo::oauth::TempCredentials->::xo::oauth::Credentials ::xo::oauth::TokenCredentials ::xo::oauth::TokenCredentials ::xo::oauth::TokenCredentials->::xo::oauth::Credentials ::xo::oauth::ClientCredentials ::xo::oauth::ClientCredentials ::xo::oauth::ClientCredentials->::xo::oauth::Credentials

Class ::xo::db::CrItem

::xo::db::CrItem[i] create ... \
           [ -package_id package_id ] \
           [ -parent_id (default "-100") ] \
           [ -publish_status (default "ready") ] \
           [ -storage_type (default "text") ]

Defined in

Class Relations

  • class: ::xo::db::CrClass[i]
  • superclass: ::xo::db::Object[i]
  • instmixin: ::xo::db::CrCache::Item[i]
  • subclass: ::xo::oauth::ServerMetadata[i], ::xo::db::image[i], ::xo::oauth::ClientMetadata[i], ::xowiki::Page[i], ::xo::db::CrFolder[i], ::xo::oauth::Credentials[i]
::xo::db::CrClass create ::xo::db::CrItem \
     -superclass ::xo::db::Object \
     -instmixin ::xo::db::CrCache::Item

Methods (to be applied on instances)

  • changed_redirect_url (scripted)

    return ""
  • current_user_id (scripted)

    if {[nsf::is object ::xo::cc]} {return [::xo::cc user_id]}
    if {[ns_conn isconnected]}  {return [ad_conn user_id]}
    return ""
  • delete (scripted, public)

     <instance of xo::db::CrItem[i]> delete

    Delete the item from the content repository with the item_id taken from the instance variable.

    Testcases:
    test_cr_items
    # delegate deletion to the class
    [:info class] delete -item_id ${:item_id}
  • description (setter)

  • fix_content (scripted)

    [:info class] instvar storage_type
    # ::msg "--long_text_slots: [[:info class] array get long_text_slots]"
    # foreach {slot_name slot} [[:info class] array get long_text_slots] {
    #   set cls [$slot domain]
    #   set content [set :$slot_name]
    #   :msg "$slot_name [$cls table_name] [$cls id_column] length=[string length $content]"
    # }
    if {![info exists :storage_type] || $storage_type ne ${:storage_type}} {
      ad_log warning "we cannot get rid of the instvar storage_type yet"  "(exists [info exists :storage_type], instvar '$storage_type',"  "value '[expr {[info exists :storage_type] ? ${:storage_type} : {UNKNOWN}}]')"
    }
    if {$storage_type eq "file"} {
      ::xo::dc dml fix_content_length "update cr_revisions  set content_length = [ad_file size ${:import_file}]  where revision_id = :revision_id"
    }
  • initialize_loaded_object (scripted)

    # empty body, to be refined
  • is_cached_object (scripted)

    return [info exists :__cached_object]
  • is_package_root_folder (scripted, public)

     <instance of xo::db::CrItem[i]> is_package_root_folder

    # In general, every cr_item may be in the role of a # "root-folder" of a package.

    Testcases:
    create_folder_with_page, create_workflow_with_instance
    # e.g. the -100 folder has no package_id
    # if {$package_id eq ""} {return false}
    if {![info exists :item_id]} {
      return false
    }
    #::xo::Package require ${:package_id}
    return [expr {${:item_id} eq [::${:package_id} folder_id]} ? true : false]
  • item_id (setter)

  • mime_type (setter)

  • name (setter)

  • nls_language (setter)

  • package_id (setter)

  • parent_id (setter)

  • privilege=creator (scripted, public)

     <instance of xo::db::CrItem[i]> privilege=creator [ -login login ] \
        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.

    Switches:
    -login (optional, defaults to "true")
    Parameters:
    user_id (required)
    package_id (required)
    method (required)

    Testcases:
    No testcase defined.
    set allowed 0
    # :log "--checking privilege [self args]"
    if {[info exists :creation_user]} {
      if {${: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
  • publish_date (setter)

  • publish_status (setter)

  • rename (scripted, public)

     <instance of xo::db::CrItem[i]> rename -old_name old_name  \
        -new_name new_name 

    Rename a content item

    Switches:
    -old_name (required)
    -new_name (required)

    Testcases:
    create_form_with_form_instance
    set item_id ${:item_id}
    ::xo::dc dml update_rename  "update cr_items set name = :new_name where item_id = :item_id"
    set :name $new_name
    :update_item_index
  • revision_id (setter)

  • save (scripted, public)

     <instance of xo::db::CrItem[i]> save \
        [ -modifying_user modifying_user ] [ -live_p on|off ] \
        [ -use_given_publish_date on|off ]

    Updates an item in the content repository. We insert a new revision instead of changing the current revision.

    Switches:
    -modifying_user (optional)
    -live_p (optional, boolean, defaults to "true")
    make this revision the live revision
    -use_given_publish_date (optional, boolean, defaults to "false")

    Testcases:
    xotcl_core_tutorial_4, test_cr_items
    set __atts [list creation_user]
    set __vars $__atts
    if {[ns_conn isconnected]} {
      lappend __atts creation_ip
      set peeraddr [ad_conn peeraddr]
      lappend __vars peeraddr
    }
    
    #
    # The modifying_user is not maintained by the CR (bug?).
    # xotcl-core handles this by having the modifying user as
    # creation_user of the revision.
    #
    # Caveat: the creation_user fetched can be different if we fetch
    # via item_id (the creation_user is the creator of the item) or if
    # we fetch via revision_id (the creation_user is the creator of
    # the revision).
    
    set creation_user [expr {[info exists modifying_user] ?
                             $modifying_user :
                             [:current_user_id]}]
    #set old_revision_id ${:revision_id}
    
    foreach {__slot_name __slot} [[:info class] array get db_slot] {
      if {
          [$__slot domain] eq "::xo::db::Object"
          || $__slot in {
            "::xo::db::CrItem::slot::name"
            "::xo::db::CrItem::slot::publish_date"
          }
        } continue
      #ns_log notice "REMAINING SLOT: [$__slot serialize]"
      set $__slot_name [set :$__slot_name]
      lappend __atts [$__slot column_name]
      lappend __vars $__slot_name
    }
    
    if {$use_given_publish_date} {
      if {"publish_date" ni $__atts} {
        set publish_date ${:publish_date}
        lappend __atts publish_date
        lappend __vars publish_date
      }
      set publish_date_flag [list -publish_date $publish_date]
    } else {
      set publish_date_flag ""
    }
    
    ::xo::dc transaction {
      #
      # Provide a row-lock to protect against deadlocks during
      # concurrent updates on the same item in different threads.
      #
      ::xo::dc row_lock -for "no key update" -prepare integer item_lock {
        select item_id from cr_items where item_id = :item_id
      }
    
      [:info class] instvar storage_type
      set revision_id [xo::dc nextval acs_object_id_seq]
      if {$storage_type eq "file"} {
        #
        # Get the mime_type from the file, eventually creating a new
        # one if it's unrecognized.
        #
        set :mime_type [cr_check_mime_type  -mime_type ${:mime_type}  -filename  ${:name}  -file      ${:import_file}]
        set :text [cr_create_content_file $item_id $revision_id ${:import_file}]
        set text ${:text}
        set mime_type ${:mime_type}
      }
      ::xo::dc [::xo::dc insert-view-operation] revision_add  [[:info class] insert_statement $__atts $__vars]
    
      :fix_content $revision_id $text
    
      if {$live_p} {
        #
        # Update the life revision with the publish status and
        # optionally the "publish_date".
        #
        ::acs::dc call content_item set_live_revision  -revision_id $revision_id  -publish_status ${:publish_status}  -is_latest true  {*}$publish_date_flag
        set :revision_id $revision_id
        :update_item_index
      } else {
        #
        # If we do not make the revision live, use the old
        # revision_id, and let CrCache save it ......
        #
      }
    
      #
      # Update instance variables "modifying_user" and "last_modified"
      # from potentially changed DB values.
      #
      set :modifying_user $creation_user
      ::xo::dc 1row -prepare integer get_metadata {
        select last_modified
        from acs_objects where object_id = :revision_id
      }
      set :last_modified $last_modified
    
      #
      # In case the context_id has in the DB is different as in the
      # instance variable, push the value from the instance variable
      # to the DB as well.
      #
      if {[info exists :context_id]} {
        set context_id ${:context_id}
    
        ::xo::dc dml update_context {
          UPDATE acs_objects
          SET context_id = :context_id
          WHERE object_id = :item_id
          AND   context_id != :context_id
        }
      }
    }
    return $item_id
  • save_new (scripted, public)

     <instance of xo::db::CrItem[i]> save_new [ -package_id package_id ] \
        [ -creation_user creation_user ] [ -creation_ip creation_ip ] \
        [ -context_id context_id ] [ -live_p on|off ] \
        [ -use_given_publish_date on|off ]

    Insert a new item to the content repository.

    Switches:
    -package_id (optional)
    -creation_user (optional)
    user_id if the creating user
    -creation_ip (optional)
    -context_id (optional)
    -live_p (optional, boolean, defaults to "true")
    make this revision the live revision
    -use_given_publish_date (optional, boolean, defaults to "false")

    Testcases:
    xotcl_core_tutorial_4, test_cr_items
    
    set __class [:info class]
    
    if {![info exists package_id] && [info exists :package_id]} {
      set package_id ${:package_id}
    }
    if {![info exists context_id]} {
      set context_id [expr {[info exists :context_id] ? ${:context_id} : ""}]
    }
    [self class] get_context package_id creation_user creation_ip
    set :creation_user $creation_user
    set __atts  [list creation_user]
    set __vars $__atts
    
    # :log "db_slots for $__class: [$__class array get db_slot]"
    foreach {__slot_name __slot} [$__class array get db_slot] {
      # :log "--slot = $__slot"
      if {
          [$__slot domain] eq "::xo::db::Object"
          || $__slot in {
            "::xo::db::CrItem::slot::name"
            "::xo::db::CrItem::slot::publish_date"
          }
        } continue
      :instvar $__slot_name
      if {![info exists $__slot_name]} {set $__slot_name ""}
      lappend __atts [$__slot column_name]
      lappend __vars $__slot_name
    }
    
    if {$use_given_publish_date} {
      if {"publish_date" ni $__atts} {
        set publish_date ${:publish_date}
        lappend __atts publish_date
        lappend __vars publish_date
      }
      set publish_date_flag [list -publish_date $publish_date]
    } else {
      set publish_date_flag ""
    }
    
    ::xo::dc transaction {
      $__class instvar storage_type object_type
      [self class] lock acs_objects "SHARE ROW EXCLUSIVE"
      set revision_id [xo::dc nextval acs_object_id_seq]
      set :revision_id $revision_id
    
      if {![info exists :name] || ${:name} eq ""} {
        # we have an autonamed item, use a unique value for the name
        set :name [expr {[info exists :__autoname_prefix] ?
                         "${:__autoname_prefix}$revision_id" : $revision_id}]
      }
      if {$title eq ""} {
        set title [expr {[info exists :__title_prefix] ?
                         "${:__title_prefix} (${:name})" : ${:name}}]
      }
    
      if {$storage_type eq "file"} {
        #
        # Get the mime_type from the file, eventually creating a new
        # one if it's unrecognized.
        #
        set mime_type [cr_check_mime_type  -mime_type $mime_type  -filename  ${:name}  -file      ${:import_file}]
      }
    
      set :item_id [::acs::dc call content_item new  -name            ${:name}  -parent_id       ${:parent_id}  -creation_user   $creation_user  -creation_ip     $creation_ip  -context_id      $context_id  -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  -with_child_rels f]
    
      if {$storage_type eq "file"} {
        set text [cr_create_content_file ${:item_id} $revision_id ${:import_file}]
      }
    
      ::xo::dc [::xo::dc insert-view-operation] revision_add  [[:info class] insert_statement $__atts $__vars]
      :fix_content $revision_id $text
    
      if {$live_p} {
        #
        # Update the life revision with the publish status and
        # optionally the publish_date
        #
        ::acs::dc call content_item set_live_revision  -revision_id $revision_id  -publish_status ${:publish_status}  -is_latest true  {*}$publish_date_flag
        :update_item_index
      }
    }
    
    :db_1row [:qn get_dates] {
      select creation_date, last_modified
      from acs_objects where object_id = :revision_id
    }
    set :object_id ${:item_id}
    return ${:item_id}
  • set_live_revision (scripted, public)

     <instance of xo::db::CrItem[i]> set_live_revision \
        -revision_id revision_id  [ -publish_status publish_status ] \
        [ -is_latest on|off ]
    Switches:
    -revision_id (required)
    -publish_status (optional, defaults to "ready")
    one of 'live', 'ready' or 'production'
    -is_latest (optional, boolean, defaults to "false")

    Testcases:
    create_folder_with_page, create_workflow_with_instance
    ::acs::dc call content_item set_live_revision  -revision_id $revision_id  -publish_status $publish_status  -is_latest $is_latest
    ::xo::xotcl_object_cache flush ${:item_id}
    ::xo::xotcl_object_cache flush $revision_id
  • storage_type (setter)

  • text (setter)

  • title (setter)

  • update (scripted)

    ::xo::dc transaction {
      next
      :instvar object_id publish_date nls_language description name mime_type text title item_id
      ::xo::dc dml update_cr_revisions {update cr_revisions
        set publish_date = :publish_date,nls_language = :nls_language,description = :description,name = :name,mime_type = :mime_type,text = :text,title = :title,item_id = :item_id where revision_id = :object_id
      }
    }
  • update_attribute_from_slot (scripted)

     <instance of xo::db::CrItem[i]> update_attribute_from_slot

    Testcases:
    slot_interactions, xowiki
    set :[$slot name] $value
    if {![info exists revision_id]} {
      set revision_id ${:revision_id}
    }
    set domain [$slot domain]
    #set sql "update [$domain table_name]  #          set [$slot column_name] = '$value'  #  where [$domain id_column] = $revision_id"
    #ns_log notice UPDATE-$sql
    ::xo::dc dml update_attribute_from_slot [subst {
      update [$domain table_name]
      set [$slot column_name] = :value
      where [$domain id_column] = :revision_id
    }]
    #
    # Probably we should call here update_last_modified, but for
    # that we would need the modifying_user and the modifying IP
    # address.
    #
    # ::acs::dc call acs_object update_last_modified  #      -object_id $revision_id  #      -modifying_user ${:publish_status}  #      -modifying_ip ...
    
    ::xo::dc dml update_attribute_from_slot_last_modified {
      update acs_objects set last_modified = CURRENT_TIMESTAMP
      where object_id = :revision_id
    }
  • update_content (scripted)

    #
    # This method can be use to update the content field (only this) of
    # a content item without creating a new revision. This works
    # currently only for storage_type == "text".
    #
    [:info class] instvar storage_type
    if {$storage_type eq "file"} {
      :log "--update_content not implemented for type file"
    } else {
      ::xo::dc dml update_content "update cr_revisions set content = :content  where revision_id = :revision_id"
    }
  • update_item_index (scripted, public)

     <instance of xo::db::CrItem[i]> update_item_index

    Dummy stub to allow subclasses to produce a more efficient index for items based on live revisions.

    Testcases:
    xotcl_core_tutorial_4, xowiki_test_cases
    next
  • update_revision (scripted)

    #
    # This method can be use to update arbitrary fields of
    # a revision.
    #
    if {$quoted} {set val $value} {set val :value}
    ::xo::dc dml update_content "update cr_revisions set $attribute = $val  where revision_id = :revision_id"
  • www-revisions (scripted)

    
    set isAdmin [acs_user::site_wide_admin_p]
    
    ::TableWidget create t1 -volatile  -columns {
          Field version_number -label "" -html {align right}
          AnchorField create view -CSSclass view-item-button -label ""
          AnchorField diff -label ""
          AnchorField plain_diff -label ""
          AnchorField author -label [_ acs-content-repository.Creation_User]
          Field content_size -label [_ acs-content-repository.Size] -html {align right}
          Field last_modified_ansi -label [_ acs-content-repository.Last_Modified]
          Field description -label [_ acs-content-repository.Description]
          if {[acs_user::site_wide_admin_p]} {AnchorField show -label ""}
          ImageAnchorField live_revision -label [_ xotcl-core.live_revision]  -src /resources/acs-subsite/radio.gif  -width 16 -height 16 -border 0 -html {align center}
          AnchorField create version_delete -CSSclass delete-item-button -label ""
        }
    
    set user_id [:current_user_id]
    set page_id ${:item_id}
    set live_revision_id [::acs::dc call content_item get_live_revision -item_id $page_id]
    set package_id ${:package_id}
    set base [::$package_id url]
    set sql [::xo::dc select  -map_function_names true  -vars "ci.name, r.revision_id as version_id, person__name(o.creation_user) as author,  o.creation_user as author_id,  to_char(o.last_modified,'YYYY-MM-DD HH24:MI:SS') as last_modified_ansi, r.description, acs_permission.permission_p(r.revision_id,:user_id,'admin') as admin_p, acs_permission.permission_p(r.revision_id,:user_id,'delete') as delete_p, r.content_length, content_revision__get_number(r.revision_id) as version_number "  -from  "cr_items ci, cr_revisions r, acs_objects o"  -where "ci.item_id = :page_id and r.item_id = ci.item_id and o.object_id = r.revision_id
                         and acs_permission.permission_p(r.revision_id, :user_id, 'read') = 't'"  -orderby "r.revision_id desc"]
    
    ::xo::dc foreach revisions_select $sql {
      set content_size_pretty [lc_content_size_pretty -size $content_length]
    
      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:  -view ""  -view.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 ""  -version_delete.title [_ acs-content-repository.Delete_Revision]
    
      [t1 last_child] set payload(revision_id) $version_id
    
      if {$isAdmin} {
        set show_revision_link [export_vars -base $base  {{m show-object} {revision_id $version_id}}]
        [t1 last_child] set show show
        [t1 last_child] set show.href $show_revision_link
      }
    
    }
    
    # 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]
    for {set i 0} {$i < [llength $lines]-1} {incr i} {
      set e [lindex $lines $i]
      set n [lindex $lines $i+1]
      set revision_id [$e set payload(revision_id)]
      set compare_revision_id [$n set payload(revision_id)]
      $e set diff.href [export_vars -base $base {{m diff} compare_revision_id revision_id}]
      $e set diff "diff"
      $e set plain_diff.href [export_vars -base $base {{m diff} {plain_text_diff 1} compare_revision_id revision_id}]
      $e set plain_diff "plain"
    }
    set e [lindex $lines end]
    if {$e ne ""} {
      $e set diff.href ""
      $e set diff ""
      $e set plain_diff.href ""
      $e set plain_diff ""
    }
    
    return [t1 asHTML]