- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables
Class ::xowf::WorkflowPage
::xowf::WorkflowPage create ...
Defined in
Class Relations
::xotcl::Class create ::xowf::WorkflowPage \ -superclass ::xotcl::ObjectMethods (to be applied on instances)
activate (scripted)
# # Execute action and compute next state of the action. # set actionObj [$ctx wf_definition_object $action] # # Check, if action is defined. # if {![nsf::is object $actionObj]} { # # There is no such action the current context. # if {$verbose} {ns_log notice "Warning: ${:name} No action $action in workflow context"} return "" } # # Activate action # ad_try { $actionObj activate [self] } on error {errorMsg errorDict} { # # Something went wrong in the application specific # code. Depending on batch_mode, report the error to the user or # to the variable __evaluation_error in the package object. # #:log "--WF: error in action $action ERRORDICT <$errorDict>" set errorInfo [dict get $errorDict -errorinfo] set error "error in action '$action' of workflow instance ${:name} of workflow [${:page_template} name]:" if {[::${:package_id} exists __batch_mode]} { ::${:package_id} set __evaluation_error "$error\n\n$errorInfo" incr validation_errors } else { :msg -html 1 "$error <pre>[ns_quotehtml $errorInfo]</pre>" } ad_log error "--WF: evaluation $error\n$errorInfo" set next_state "" } on ok {result} { # # The action went ok. The call to "get_next_state" is here to # allow the developer to influence the outcome of # "get_next_state" by the activated method. # set next_state [$actionObj get_next_state] #:log "ACTIVATE ${:name} no error next-state <$next_state>" } return $next_stateanswer_is_correct (scripted, public)
<instance of xowf::WorkflowPage> answer_is_correctCheck, if answer is correct based on "answer" and "correct_when" attributes of form fields and provided user input.
- Testcases:
- No testcase defined.
set correct 0 :log "WorkflowPage(${:name}).answer_is_correct autocorrect '[:get_from_template auto_correct]' -- [string is true -strict [:get_from_template auto_correct]]" if {[string is true -strict [:get_from_template auto_correct]]} { :log "==== answer_is_correct '[:instantiated_form_fields]'" foreach f [:instantiated_form_fields] { #:log [$f serialize] #:log "checking correctness [$f name] [$f info class] answer?[$f exists value] correct_when ?[$f exists correct_when]" if {[$f exists value]} { set r [$f answer_is_correct] #:log [$f serialize] if {$r != 1} { #:log [$f serialize] #:log "checking correctness [$f name] failed ([$f answer_is_correct])" set correct -1 break } set correct 1 } } } return $correctcall_action (scripted, public)
<instance of xowf::WorkflowPage> call_action [ -action action ] \ [ -attributes attributes ]Call the specified action in the current workflow instance. The specified attributes are provided like form_parameters to the action of the workflow.
- Switches:
- -action (optional)
- -attributes (optional)
- Testcases:
- No testcase defined.
if {![:is_wf_instance]} { error "Page [self] is not a Workflow Instance" } set actionObj [:get_action_obj -action $action] return [$actionObj invoke -attributes $attributes]call_action_foreach (scripted, public)
<instance of xowf::WorkflowPage> call_action_foreach \ -action action [ -attributes attributes ] page_namesCall the specified action for each of the specified pages denoted by the list of page names
- Switches:
- -action (required)
- -attributes (optional)
- Parameters:
- page_names (required)
- Testcases:
- No testcase defined.
foreach page_name $page_names { set page [${:package_id} get_page_from_name -parent_id [:parent_id] -name $page_name] if {$page ne ""} { $page call_action -action $action -attributes $attributes } else { ns_log notice "WF: could not call action $action, since $page_name in [:parent_id] failed" } }check_role (scripted)
if {[::xo::cc info methods role=$role] eq ""} { :msg "ignoring unknown role '$role'" return 0 } if {$role eq "creator"} { # # Meaning: "creator of the object", requires the object as # additional attribute. # return [::xo::cc role=$role -object [self] -user_id [::xo::cc user_id] -package_id [:package_id]] } else { return [::xo::cc role=$role -user_id [::xo::cc user_id] -package_id ${:package_id}] }childpage (scripted, public)
<instance of xowf::WorkflowPage> childpage -name name \ [ -form form ]Return the child page of the current object with the provided name. In case the child object does not exist, create it as an instance of the provided form.
- Switches:
- -name (required)
- -form (optional)
- Returns:
- page object
- Testcases:
- create_test_items
if {[info exists form]} { set child_page_id [::${:package_id} lookup -use_package_path false -default_lang en -name $name -parent_id ${:item_id}] if {$child_page_id == 0} { ns_log notice "child page '$name' does not exist" set form_obj [::${:package_id} instantiate_forms -default_lang "en" -forms $form] if {[llength $form_obj] == 0} { error "childpage: cannot instantiate $form" } set p [$form_obj create_form_page_instance -name $name -nls_language en_US -parent_id ${:item_id} -package_id ${:package_id} -instance_attributes {}] $p save_new } else { #ns_log notice "child page '$name' exists already (item_id $child_page_id)" set p [::xo::db::CrClass get_instance_from_db -item_id $child_page_id] } return $p } else { error "cannot create '$name': API supports so far only form pages" }constraints_as_dict (scripted)
set result "" foreach name_and_spec $c { set p [string first : $name_and_spec] if {$p > -1} { set spec_name [string range $name_and_spec 0 $p-1] set short_spec [string range $name_and_spec $p+1 end] if {$short_spec eq "" && [dict exists $fc_repository $spec_name]} { set short_spec [dict get $fc_repository $spec_name] #:log "======= use fc_repository for <$spec_name> <$short_spec>" } dict set result $spec_name $short_spec } else { ns_log warning "ignore invalid fc: <$name_and_spec>" } } return $resultcreate-or-use_view (scripted)
# the link should be able to view return_url and template_file return [::$package_id returnredirect [::$package_id pretty_link -parent_id $parent_id $lang:$stripped_name]]debug_msg (scripted)
#util_user_message -message $msg ns_log notice "--WF $msg" catch {ds_comment $msg}default_instance_attributes (scripted)
# Provide the default list of instance attributes to derived # FormPages. if {[:is_wf]} { # # We have a workflow page. Get the initial state of the workflow # instance from the workflow. # set instance_attributes "" set ctx [::xowf::Context require [self]] foreach p [$ctx defined ::xowiki::formfield::FormField] { set name [$p name] set value [$p default] if {[::xo::cc exists_query_parameter $name]} { # # Never clobber instance attributes from query parameters # blindly. # #:msg "ignore $name" continue } if {[::xo::cc exists_query_parameter p.$name] && [$p exists allow_query_parameter]} { # # We allow the value to be taken from the query parameter. # set value [::xo::cc query_parameter p.$name] $p value $value $p validate $p } dict set instance_attributes $name $value set f($name) $p } ## save instance attributes #set instance_attributes [array get __ia] #:msg "[self] ${:name} setting default parameter" #:log ia=$instance_attributes,props=[$ctx defined Property] :state [$ctx get_current_state] #:msg "setting initial state to '[:state]'" return $instance_attributes } else { next }evaluate_form_field_condition (scripted)
set ctx [::xowf::Context require [self]] if {[nsf::is object ${ctx}::$cond]} { return [${ctx}::$cond] } return 0footer (scripted, public)
<instance of xowf::WorkflowPage> footerProvide a tailored footer for workflow definition pages and workflow instance pages containing controls for instantiating forms or providing links to the workflow definition.
- Testcases:
- create_workflow_with_instance
if {[info exists :__no_form_page_footer]} { next } else { set parent_id [:parent_id] set form_item_id ${:page_template} #:msg "is wf page [:is_wf], is wf instance page [:is_wf_instance]" if {[:is_wf]} { # # page containing a work flow definition # #set ctx [::xowf::Context require [self]] set work_flow_form [::xo::db::CrClass get_instance_from_db -item_id $form_item_id] set work_flow_base [$work_flow_form pretty_link] set wf [self] set wf_base [$wf pretty_link] set button_objs [list] # create new workflow instance button with start form #if {[:parent_id] != [::${:package_id} folder_id]} { # set parent_id [:parent_id] #} set link [::${:package_id} make_link -link $wf_base $wf create-new parent_id return_url] lappend button_objs [::xowiki::includelet::form-menu-button-new new -volatile -parent_id $parent_id -form $wf -link $link] # list workflow instances button set obj [::xowiki::includelet::form-menu-button-wf-instances new -volatile -package_id ${:package_id} -parent_id $parent_id -base $wf_base -form $wf] if {[info exists return_url]} { $obj return_url $return_url } lappend button_objs $obj # work flow definition button set obj [::xowiki::includelet::form-menu-button-form new -volatile -package_id ${:package_id} -parent_id $parent_id -base $work_flow_base -form $work_flow_form] if {[info exists return_url]} {$obj return_url $return_url} lappend button_objs $obj # make menu return [:include [list form-menu -form_item_id ${:item_id} -button_objs $button_objs]] } elseif {[:is_wf_instance]} { # # work flow instance # set entry_form_item_id [:wf_property wf_form_id] set work_flow_form [::xo::db::CrClass get_instance_from_db -item_id $form_item_id] set work_flow_base [$work_flow_form pretty_link] set button_objs [list] #:msg entry_form_item_id=$entry_form_item_id-exists?=[nsf::is object $entry_form_item_id] # form definition button if {![nsf::is object $entry_form_item_id]} { # In case, the id is a form object, it is a dynamic form, # that we can't edit; therefore, we provide no link. # # Here, we have an id that we use for fetching... # set form [::xo::db::CrClass get_instance_from_db -item_id $entry_form_item_id] set base [$form pretty_link] set obj [::xowiki::includelet::form-menu-button-form new -volatile -package_id ${:package_id} -parent_id $parent_id -base $base -form $form] if {[info exists return_url]} { $obj return_url $return_url } lappend button_objs $obj } # # work flow definition button # set obj [::xowiki::includelet::form-menu-button-wf new -volatile -package_id ${:package_id} -parent_id $parent_id -base $work_flow_base -form $work_flow_form] if {[info exists return_url]} {$obj return_url $return_url} lappend button_objs $obj # make menu return [:include [list form-menu -form_item_id ${:page_template} -button_objs $button_objs]] } else { next } }get_action_obj (scripted, public)
<instance of xowf::WorkflowPage> get_action_obj -action actionCheck if the action can be executed in the current state, and if so, return the action_obj.
- Switches:
- -action (required)
- Testcases:
- create_workflow_with_instance
set ctx [::xowf::Context require [self]] # # First try to call the action in the current state # foreach a [$ctx get_actions] { if {[namespace tail $a] eq "$action"} { # In the current state, the specified action is allowed :log "--xowf action $action allowed -- name='${:name}'" return $a } } # # Some actions are state-safe, these can be called in every state # set actionObj [$ctx wf_definition_object $action] if {[nsf::is object $actionObj] && [$actionObj state_safe]} { # The action is defined as state-safe, so if can be called in every state :log "--xowf action $action state_safe -- name='${:name}'" return $actionObj } error "No state-safe action '$action' available in workflow instance [self] of [${:page_template} name] in state [$ctx get_current_state]\n Available actions: [[$ctx current_state] get_actions]"get_anon_instances (scripted)
if {[:istype ::xowiki::FormPage] && [:is_wf_instance]} { # # In case, the workflow definition has the autoname variable set, # it has the highest weight of all other sources. # set wfc [[::xowf::Context require [self]] wf_container] if {[$wfc exists autoname]} { return [$wfc set autoname] } } nextget_assignee (scripted)
return [:assignee]get_fc_repository (scripted)
set container [[:wf_context] wf_container] if {[$container exists fc_repository]} { return [$container set fc_repository] } #ns_log warning "get_fc_repository returns empty" return ""get_form_constraints (scripted)
#:log "" if {[:istype ::xowiki::FormPage] && [:is_wf]} { #:msg "get_form_constraints is_wf" return [::xo::cc cache [list [self] wf_merged_form_constraints [next]]] } elseif {[:istype ::xowiki::FormPage] && [:is_wf_instance]} { #:msg "get_form_constraints is_wf_instance" return [::xo::cc cache [list [self] wfi_merged_form_constraints [next]]] } else { #:msg "get_form_constraints next" next }get_form_data (scripted)
if {[:is_wf_instance]} { lassign [next] validation_errors category_ids if {$validation_errors == 0} { #:msg "validation ok" set ctx [::xowf::Context require [self]] set cc [${:package_id} context] foreach {name value} [$cc get_all_form_parameter] { if {[regexp {^__action_(.+)$} $name _ action]} { set actionObj [:get_action_obj -action $action] set next_state [:activate $ctx $action] #:log "after activate next_state=$next_state, current_state=[$ctx get_current_state], ${:instance_attributes}" if {$next_state ne ""} { if {[$actionObj exists assigned_to]} { :assignee [:get_assignee [$actionObj assigned_to]] } $ctx set_current_state $next_state } break } } } #ns_log notice "===== get_form_data returns [list $validation_errors $category_ids]" return [list $validation_errors $category_ids] } else { next }get_revision_sets (scripted, public)
<instance of xowf::WorkflowPage> get_revision_sets \ [ -with_instance_attributes ]Return a list of ns_sets containing revision_id, creation_date, creation_user, creation_ip, and state for the current workflow instance.
- Switches:
- -with_instance_attributes (optional)
- Testcases:
- create_test_items
set item_id ${:item_id} if {$with_instance_attributes} { set revision_sets [::xo::dc sets -prepare integer wf_revisions { SELECT revision_id, creation_date, last_modified, creation_user, creation_ip, state, assignee, instance_attributes FROM cr_revisions cr, acs_objects o, xowiki_form_page x, xowiki_page_instance pi WHERE cr.item_id = :item_id AND o.object_id = cr.revision_id AND x.xowiki_form_page_id = cr.revision_id AND pi.page_instance_id = cr.revision_id ORDER BY cr.revision_id ASC }] } else { set revision_sets [::xo::dc sets -prepare integer wf_revisions { SELECT revision_id, creation_date, last_modified, creation_user, creation_ip, state, assignee FROM cr_revisions cr, acs_objects o, xowiki_form_page x WHERE cr.item_id = :item_id AND o.object_id = cr.revision_id AND x.xowiki_form_page_id = cr.revision_id ORDER BY cr.revision_id ASC }] } return $revision_setsget_template_object (scripted)
if {[:is_wf_instance]} { set key :__wfi(wf_form_id) if {![info exists $key]} { set ctx [::xowf::Context require [self]] set $key [$ctx form_object [self]] } set form_obj [set $key] if {![nsf::is object $form_obj]} { ad_log error "deprecated usage: method 'form_object' did NOT return an object. Will raise an error in the future" set form_id [string trimleft $form_obj :] set form_obj [::xo::db::CrClass get_instance_from_db -item_id $form_id] } return $form_obj } else { return [next] }hstore_attributes (scripted)
# # We do not want to save the workflow definition in every workflow # instance. # return [dict remove ${:instance_attributes} workflow_definition]initialize (scripted)
#:log "START-initialize is_wf_instance [:is_wf_instance]" # # A fresh workflow page was created (called only once per # workflow page at initial creation) # if {[:is_wf_instance]} { # # Get context and call user defined "constructor" # # set the state to a well defined starting point if {${:state} eq ""} {set :state initial} set ctx [::xowf::Context require -new [self]] :activate -verbose false $ctx initialize # Ignore the returned next_state, since the initial state is # always set to the same value from the ctx (initial) #:msg "[self] is=${:instance_attributes}" } elseif {[:is_wf] && [info exists :item_id]} { # # We are initializing a fully created workflow object. # # The test for "exists :item_id" is important, since when a # workflow is created via "create_form_page_instance", the # workflow object is create via "new", it has not been saved yet # and has therefore no "item_id" yet. # set ctx [::xowf::Context require -new [self]] set code [[$ctx wf_container] wf-specific] #ns_log notice "...initialize wf, wf-specific code: $code" if {$code ne ""} { eval $code } } next #:log END-initializeinitialize_loaded_object (scripted)
next # # Call "initialize" for workflows and workflow instances. Before, # we called "initialize" only, when [:is_wf_instance] was true. # if {[:is_wf_instance] || [:is_wf]} { :initialize }instantiated_form_fields (scripted)
# Helper method to # - obtain the field_names from the current form, to # - create form_field instances from that and to # - provide the values from the instance attributes into it. lassign [:field_names_from_form] _ field_names set form_fields [:create_form_fields $field_names] :load_values_into_form_fields $form_fields return $form_fieldsis_wf (scripted, public)
<instance of xowf::WorkflowPage> is_wfCheck, if the current page is a workflow page (page, defining a workflow)
- Testcases:
- create_test_items, create_workflow_with_instance
if {[info exists :__wf(workflow_definition)]} { return 1 } elseif {[:property workflow_definition] ne ""} { array set :__wf ${:instance_attributes} return 1 } else { return 0 }is_wf_instance (scripted, public)
<instance of xowf::WorkflowPage> is_wf_instanceCheck, if the current page is a workflow instance (page, referring to a workflow)
- Testcases:
- create_test_items, create_workflow_with_instance
if {[array exists :__wfi]} { return 1 } # # We cannot call get_template_object here, because this will lead # to a recursive loop. # if {![nsf::is object ::${:page_template}]} { ::xo::db::CrClass get_instance_from_db -item_id ${:page_template} } if {${:state} ne "" && [${:page_template} hasclass ::xowf::WorkflowPage] && [${:page_template} is_wf] } { array set :__wfi [${:page_template} instance_attributes] return 1 } return 0merge_constraints (scripted)
# Load into the base_constraints c1 the constraints from the argument list. # The first constraints have the lowest priority set fcrepo [:constraints_as_dict [:get_fc_repository]] set merged [:constraints_as_dict -fc_repository $fcrepo $c1] foreach c2 $args { foreach {att value} [:constraints_as_dict -fc_repository $fcrepo $c2] { if {[dict exists $merged $att]} { dict append merged $att ",$value" } else { dict set merged $att "$value" } } } return [lmap {att value} $merged {string cat $att:$value}]post_process_dom_tree (scripted, public)
<instance of xowf::WorkflowPage> post_process_dom_tree dom_doc \ dom_root form_fieldspost-process form in edit mode to provide feedback in feedback mode
- Parameters:
- dom_doc (required)
- dom_root (required)
- form_fields (required)
- Testcases:
- create_workflow_with_instance
# In feedback mode, we set the CSS class to correct or incorrect if {[info exists :__feedback_mode]} { unset :__feedback_mode ::xo::Page requireCSS /resources/xowf/feedback.css set form [lindex [$dom_root selectNodes "//form"] 0] $form setAttribute class "[$form getAttribute class] feedback" # # In cases, where the HTML exercise was given, we process the HTML # to flag the result. # # TODO: What should we do with the feedback. "util_user_message" is # not optimal... # foreach f $form_fields { if {[$f exists __rendered]} continue if {[$f exists evaluated_answer_result]} { set result [$f set evaluated_answer_result] foreach n [$dom_root selectNodes "//form//*\[@name='[$f name]'\]"] { set oldCSSClass [expr {[$n hasAttribute class] ? [$n getAttribute class] : ""}] $n setAttribute class [string trim "$oldCSSClass [$f form_widget_CSSclass]"] $f form_widget_CSSclass $result set helpText [$f help_text] if {$helpText ne ""} { #set divNode [$dom_doc createElement div] #$divNode setAttribute class [$f form_widget_CSSclass] #$divNode appendChild [$dom_doc createTextNode $helpText] #[$n parentNode] insertBefore $divNode [$n nextSibling] #set spanNode [$dom_doc createElement span] #$spanNode setAttribute class "glyphicon glyphicon-ok [$f form_widget_CSSclass]" #[$n parentNode] insertBefore $spanNode [$n nextSibling] set parentNode [$n parentNode] set oldClass [$parentNode getAttribute class ""] $parentNode setAttribute class "selection [$f form_widget_CSSclass]" $parentNode setAttribute title $helpText #util_user_message -message "field [$f name], value [$f value]: $helpText" } } } } # # Provide feedback for the whole exercise. # if {[:answer_is_correct]} { set feedback [:get_from_template feedback_correct] } else { set feedback [:get_from_template feedback_incorrect] } if {$feedback ne ""} { $dom_root appendFromScript { html::div -class feedback { html::t -disableOutputEscaping $feedback } } } }post_process_form_fields (scripted, public)
<instance of xowf::WorkflowPage> post_process_form_fields \ form_fieldsPropagate the feedback mode setting of this workflow page to the supplied formfields.
- Parameters:
- form_fields (required)
- Testcases:
- create_workflow_with_instance
#:log ------------------post_process_form_fields-feedback_mode=[info exists :__feedback_mode] if {[info exists :__feedback_mode]} { # # Provide feedback for every alternative # foreach f $form_fields { $f set_feedback ${:__feedback_mode} } } #:log ------------------post_process_form_fields-feedback_mode=[info exists :__feedback_mode]-DONErender_form_action_buttons (scripted, public)
<instance of xowf::WorkflowPage> render_form_action_buttons \ [ -formfieldButtonClass formfieldButtonClass ] \ [ -CSSclass CSSclass ]Render the defined actions in the current state with submit buttons
- Switches:
- -formfieldButtonClass (optional, defaults to
"::xowiki::formfield::submit_button"
)- -CSSclass (optional)
- Testcases:
- create_workflow_with_instance
if {[:is_wf_instance]} { set ctx [::xowf::Context require [self]] set buttons {} foreach action [$ctx get_actions] { set success 0 foreach role [$action roles] { set success [:check_role $role] if {$success} break } if {$success} { set f [$formfieldButtonClass new -name __action_[namespace tail $action] -form_button_wrapper_CSSclass [$action wrapper_CSSclass] -label_noquote [$action label_noquote] -CSSclass $CSSclass -destroy_on_cleanup ] if {[$action extra_css_class] ne ""} { #$f append form_button_CSSclass " " [$action extra_css_class] $f form_button_CSSclass "" $f CSSclass_list_add form_button_CSSclass [$action extra_css_class] } $f CSSclass_list_add form_button_CSSclass prevent-double-click #ns_log notice "RENDER BUTTON has CSSclass [$f CSSclass] // [$f form_button_CSSclass]" if {[$action exists title]} { $f title [$action title] } $f value [$action label] lappend buttons $f } } # # Render the button widgets. # :render_form_action_buttons_widgets -CSSclass $CSSclass $buttons } else { next }render_form_action_buttons_widgets (scripted, public)
<instance of xowf::WorkflowPage> render_form_action_buttons_widgets \ [ -CSSclass CSSclass ] buttonsWith the given set of buttons, produce the HTML for the button container and the included inputs.
- Switches:
- -CSSclass (optional)
- Parameters:
- buttons (required)
- Testcases:
- create_workflow_with_instance
if {[llength $buttons] > 0} { # # Build button groups based on "form_button_wrapper_CSSclass". # set previous_wrapper_class "NONE" set wrapper_groups {} set group_num 0 foreach f $buttons { set wrapper_class [$f form_button_wrapper_CSSclass] if {$wrapper_class eq $previous_wrapper_class} { dict lappend wrapper_groups [list $wrapper_class $group_num] $f continue } incr group_num dict lappend wrapper_groups [list $wrapper_class $group_num] $f set previous_wrapper_class $wrapper_class } foreach wrapper_group [dict keys $wrapper_groups] { ::html::div -class [lindex $wrapper_group 0] { foreach f [dict get $wrapper_groups $wrapper_group] { $f render_input } } } }render_icon (scripted, public)
<instance of xowf::WorkflowPage> render_iconProvide an icon or text for describing the kind of application.
- Testcases:
- create_workflow_with_instance
if {[:info procs render_icon] ne ""} { # # In case, we have a per-object method (i.e., defined via the # workflow), use this with highest precedence. # next } elseif {[:is_wf_instance]} { set page_template ${:page_template} set title [::$page_template title] regsub {[.]wf$} $title "" title return [list text $title is_richtext false] } elseif {[:is_wf]} { return [list text "Workflow" is_richtext false] } else { next }render_thumbnails (scripted, public)
<instance of xowf::WorkflowPage> render_thumbnails upload_infoRenderer of the thumbnail file(s)
- Parameters:
- upload_info (required)
- dict containing the "file_object" and "file_name"
- Returns:
- HTML content
- Testcases:
- No testcase defined.
dict with upload_info { set parent_id ${:item_id} set feedbackFiles [xo::dc list_of_lists . { select item_id, name from cr_items where parent_id = :parent_id }] if {[regexp {^([^/]+)/} $file_name . qn]} { set HTML [:QM render_feedback_files -question_name $qn -feedbackFiles $feedbackFiles] } else { set HTML "$file_name created" } } return $HTMLsave (scripted)
set r [next] :save_in_hstore return $rsave_data (scripted)
if {[:is_wf_instance]} { # # update the state in the workflow instance # set ctx [::xowf::Context require [self]] set prev_state ${:state} set :state [$ctx get_current_state] if {$prev_state ne ${:state}} { # The form object in the cache is still that from the previous # state, make sure we flush it. $ctx flush_form_object } } nextsave_in_hstore (scripted)
# if {[::xo::dc has_hstore] && [${:package_id} get_parameter use_hstore 0]} { set hkey [::xowiki::hstore::dict_as_hkey [:hstore_attributes]] set revision_id ${:revision_id} xo::dc dml update_hstore "update xowiki_page_instance set hkey = :hkey where page_instance_id = :revision_id" }save_new (scripted)
set r [next] :save_in_hstore return $rschedule_action (scripted, public)
<instance of xowf::WorkflowPage> schedule_action -time time \ [ -party_id party_id ] -action action [ -attributes attributes ]Schedule the specified action for the current workflow instance at the given time. The specified attributes are provided like form_parameters to the action of the workflow.
- Switches:
- -time (required)
- time when the atjob should be executed
- -party_id (optional)
- party_id for the user executing the atjob
- -action (required)
- workflow action to be executed
- -attributes (optional)
- arguments provided to the workflow action (attribute value pairs)
- Testcases:
- No testcase defined.
if {![:is_wf_instance]} { error "Page [self] is not a Workflow Instance" } if {![info exists party_id]} { set party_id [::xo::cc user_id] } :schedule_job -time $time -party_id $party_id [list call_action -action $action -attributes $attributes]schedule_job (scripted, public)
<instance of xowf::WorkflowPage> schedule_job -time time \ [ -party_id party_id ] cmdSchedule the specified Tcl command for the current package instance at the given time.
- Switches:
- -time (required)
- -party_id (optional)
- Parameters:
- cmd (required)
- Testcases:
- No testcase defined.
:log "-at $time" set j [::xowf::atjob new -time $time -party_id $party_id -cmd $cmd -url [:pretty_link] -object [self]] $j persistsend_to_assignee (scripted)
set wf_name [${:page_template} name] if {![info exists subject]} { set subject "\[$wf_name\] ${:title} (${:state})" } if {![info exists :from]} {set from ${:creation_user}} acs_user::get -user_id ${:assignee} -array to_info acs_user::get -user_id $from -array from_info set message_id [mime::uniqueID] set message_date [acs_mail_lite::utils::build_date] set tokens [mime::initialize -canonical $mime_type -encoding "quoted-printable" -string $body] if {$with_ical} { set items [::xo::OrderedComposite new -destroy_on_cleanup -mixin ::xo::ical::VCALENDAR] # hmm, mozilla just supports VEVENT, a VTODO would be nice. $items add [::xo::ical::VEVENT new -creation_date ${:creation_date} -last_modified ${:last_modified} -dtstart "now" -uid ${:package_id}-${:revision_id} -url [:pretty_link -absolute true] -summary $subject -description "Workflow instance of workflow $wf_name ${:description}"] $items configure -prodid "-//WU Wien//NONSGML XoWiki Content Flow//EN" -method request set ical [$items as_ical] lappend tokens [mime::initialize -canonical text/calendar -param [list method request] -param [list charset UTF-8] -header [list "Content-Disposition" "attachment; filename=\"todo.vcs\""] -encoding "quoted-printable" -string $ical] lappend tokens [mime::initialize -canonical application/ics -param [list name "invite.ics"] -header [list "Content-Disposition" "attachment; filename=\"todo.ics\""] -encoding "quoted-printable" -string $ical] } if {[llength $tokens]>1} { set tokens [mime::initialize -canonical "multipart/mixed" -parts $tokens] } set headers_list [list] lappend headers_list [list From $from_info(email)] [list To $to_info(email)] [list Subject $subject] set originator [acs_mail_lite::bounce_address -user_id $from -package_id ${:package_id} -message_id $message_id] acs_mail_lite::smtp -multi_token $tokens -headers $headers_list -originator $originator mime::finalize $tokens -subordinates allsolution_set (scripted, public)
<instance of xowf::WorkflowPage> solution_setCompute solution set in form of attribute=value pairs based on "answer" attribute of form fields.
- Testcases:
- No testcase defined.
set solutions [list] foreach f [:instantiated_form_fields] { if {![$f exists answer]} continue lappend solutions [$f name]=[$f answer] } return [join [lsort $solutions] ", "]stats_record_count (scripted, public)
<instance of xowf::WorkflowPage> stats_record_count nameRecord that the specified question was used.
- Parameters:
- name (required)
- Testcases:
- create_test_items
dict incr :__stats_count $namestats_record_detail (scripted, public)
<instance of xowf::WorkflowPage> stats_record_detail \ [ -label label ] [ -value value ] [ -name name ] \ [ -correctly_answered on|off ]Record the stat detail of the question.
- Switches:
- -label (optional)
- -value (optional)
- -name (optional)
- -correctly_answered (optional, boolean)
- Testcases:
- create_test_items
dict set :__stats_label $name label $value $label if {[info exists :__stats_success] && [dict exists ${:__stats_success} $name $value]} { set details [dict get ${:__stats_success} $name $value] } else { set details "" } dict incr details $correctly_answered dict set :__stats_success $name $value $detailsunset_temporary_instance_variables (scripted)
# never save/cache the following variables unset -nocomplain :__wfi unset -nocomplain :__wf nextutil_user_message (scripted)
if {[ns_conn isconnected]} { ::util_user_message -message $message -html=$html } else { ns_log notice "util_user_message suppressed (no connection): $message" }visited_states (scripted)
set item_id ${:item_id} foreach state [xo::dc list history { select DISTINCT state from xowiki_form_page p, cr_items i, cr_revisions r where i.item_id = :item_id and r.item_id = i.item_id and xowiki_form_page_id = r.revision_id}] { set visited($state) 1 } #:msg "visited states of item $item_id = [array names visited]" return [array names visited]wf_context (scripted, public)
<instance of xowf::WorkflowPage> wf_context [ ctx ]Return for a workflow page the workflow context object. The same function can be used as well for setting the workflow context at the first places (e.g. on initialization of the wf-context).
- Parameters:
- ctx (optional)
- Testcases:
- create_workflow_with_instance
if {$ctx ne ""} { set :_wf_context $ctx } return ${:_wf_context}wf_merged_form_constraints (scripted)
return $constraints_from_form #return [:merge_constraints $constraints_from_form [:property form_constraints]]wf_property (scripted)
if {[info exists :__wf]} {set key :__wf($name)} else {set key :__wfi($name)} if {[info exists $key]} { return [set $key] } return $defaultwfi_merged_form_constraints (scripted)
set ctx [::xowf::Context require [self]] set wf_specific_constraints [${:page_template} property form_constraints] set m [:merge_constraints $wf_specific_constraints $constraints_from_form [$ctx get_form_constraints]] #:msg "merged:$m" return $mwww-create-or-use (scripted)
#:msg "instance = [:is_wf_instance], wf=[:is_wf]" if {[:is_wf]} { # # In a first step, we call "allocate". Allocate is an Action # defined in a workflow, which is called *before* the workflow # instance is created. Via allocate, it is e.g. possible to # provide a computed name for the workflow instance from within # the workflow definition. # set ctx [::xowf::Context require [self]] set wfc [$ctx wf_container] :activate $ctx allocate # # After allocate, the payload might contain "name", "parent_id" # or "m". Using the payload dict has the advantage that it does # not touch the instance variables. # set payload [${wfc}::allocate payload] #ns_log notice "AFTER ALLOCATE www-create-or-use <$payload>" set m "" set title "" foreach p {name title parent_id m} { if {[dict exists $payload $p]} { set $p [dict get $payload $p] } } set package ::${:package_id} if {$title ne ""} { ::xo::cc set_query_parameter title $title } # # If these values are not set, try to obtain it the old-fashioned way. # if {$parent_id == 0} { set parent_id [:query_parameter parent_id:cr_item_of_package,arg=${:package_id} [$package folder_id]] } if {$name eq ""} { set name [:property name ""] } # # Check, if allocate has provided a name: # if {$name ne ""} { # Ok, a name was provided. Check if an instance with this name # exists in the current folder. set default_lang [:lang] $package get_lang_and_name -default_lang $default_lang -name $name lang stripped_name set id [::xo::db::CrClass lookup -name $lang:$stripped_name -parent_id $parent_id] #:log "after allocate lookup of $lang:$stripped_name returned $id, default-lang(${:name})=$default_lang [:nls_language]" if {$id != 0} { # # The instance exists already. Either call method "m" # directly (if provided) or redirect to the item. # if {$m eq ""} { return [$package returnredirect [export_vars -no_base_encode -base [$package pretty_link -parent_id $parent_id $lang:$stripped_name] {return_url template_file}]] } else { set item [::xo::db::CrClass get_instance_from_db -item_id $id] # missing: policy check. return [$item www-$m] } } else { if {$lang ne $default_lang} { set nls_language [:get_nls_language_from_lang $lang] } else { set nls_language [:nls_language] } #:msg "We want to create $lang:$stripped_name" set name $lang:$stripped_name } } } # method "m" is ignored, always edit next -parent_id $parent_id -view_method $view_method -name $name -nls_language $nls_languagewww-edit (scripted, public)
<instance of xowf::WorkflowPage> www-edit args [ args... ]Hook for editing workflow pages
- Parameters:
- args (required)
- Testcases:
- create_workflow_with_instance
if {[:is_wf_instance]} { set ctx [::xowf::Context require [self]] set s [$ctx current_state] :include_header_info -css [$s extra_css] -js [$s extra_js] } nextwww-view (scripted, public)
<instance of xowf::WorkflowPage> www-view [ content ]Provide additional view modes: - edit: instead of viewing a page, it is opened in edit mode - view_user_input: show user the provided input - view_user_input_with_feedback: show user the provided input with feedback
- Parameters:
- content (optional)
- Testcases:
- create_test_items, create_workflow_with_instance
# The edit method calls view with an HTML content as argument. # To avoid a loop, when "view" is redirected to "edit", # we make sure that we only check the redirect on views # without content. #:msg "view [self args] [:is_wf_instance]" if {[:is_wf_instance] && $content eq ""} { set ctx [::xowf::Context require [self]] set method [$ctx get_view_method] set s [$ctx current_state] :include_header_info -css [$s extra_css] -js [$s extra_js] if {$method ne "" && $method ne "view"} { #:msg "view redirects to $method in state [$ctx get_current_state]" switch -- $method { view_user_input { #:msg "calling edit with disable_input_fields=1" return [:www-edit -disable_input_fields 1] } view_user_input_with_feedback { set :__feedback_mode 1 #:msg "calling edit with disable_input_fields=1" return [:www-edit -disable_input_fields 1] } default { #:msg "calling $method" return [::${:package_id} invoke -method $method] } } } } next
- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables