%3 ::xowiki::formfield::FormField ::xowiki::formfield::FormField → fc_decode → fc_encode → get_from_name → get_single_spec → interprete_condition CSSclass_list_add add_statistics answer_check=AND answer_check=answer_words answer_check=btwn answer_check=contains answer_check=contains-not answer_check=eq answer_check=ge answer_check=gt answer_check=in answer_check=le answer_check=lt answer_check=match answer_is_correct asWidgetSpec behavior booleanAttributes config_from_spec convert_to_external convert_to_internal describe dict_to_fc dict_to_spec dict_value escape_message_keys field_value handle_transmit_always has_instance_variable init initialize interprete_single_spec is_disabled is_repeat_template_p leaf_components localize make_correct pretty_image pretty_value process_correct_when_modifier remove_omit render render_answer_statistics render_collapsed render_disabled_as_div render_error_msg render_form_widget render_help_text render_input render_item render_localizer render_modal render_result_statistics render_word_statistics repeat repeat_add_label resetBooleanAttributes reset_on_validation_error reset_parameter same_value set_disabled set_feedback set_is_repeat_template stats_record_count validate validation_check value_if_nothing_is_returned_from_form word_statistics ::xo::tdom::Object ::xo::tdom::Object ::xowiki::formfield::FormField->::xo::tdom::Object ::xowiki::formfield::file ::xowiki::formfield::file check=virus content-type convert_to_internal entry_info get_from_value get_old_value initialize label_or_value no_value_provided pretty_value render_input reset_on_validation_error store_file tmpfile value ::xowiki::formfield::file->::xowiki::formfield::FormField ::xowiki::formfield::import_archive ::xowiki::formfield::import_archive initialize pretty_value ::xowiki::formfield::import_archive->::xowiki::formfield::file ::xowiki::formfield::image ::xowiki::formfield::image pretty_value ::xowiki::formfield::image->::xowiki::formfield::file

Class ::xowiki::formfield::file

::xowiki::formfield::file[i] create ... \
           [ -choose_file_label choose_file_label ] \
           [ -link_label link_label ] \
           [ -multiple:boolean (default "false") ] \
           [ -searchable:boolean (default "false") ] \
           [ -size (default "40") ] \
           [ -sticky:boolean (default "false") ] \
           [ -viruscheck:boolean (default "true") ]

Class Relations

  • class: ::xotcl::Class[i]
  • superclass: ::xowiki::formfield::FormField[i]
  • subclass: ::xowiki::formfield::import_archive[i], ::xowiki::formfield::image[i]
::xotcl::Class create ::xowiki::formfield::file \
     -superclass ::xowiki::formfield::FormField

Methods (to be applied on instances)

  • check=virus (scripted)

    # In case of an upgrade script, the (uploaded) temporary file might not exist
    if {[:viruscheck]
        && [info exists :tmpfile]
        && $value ne ""
        && [::file exists ${:tmpfile}]
        && [::xowiki::virus check ${:tmpfile}]
      } {
      #util_user_message -message "uploaded file contains a virus; upload rejected"
      return 0
    }
    return 1
  • choose_file_label (setter)

  • content-type (scripted)

    :set [self proc] $value
  • convert_to_internal (scripted)

    
    if {[:no_value_provided] || ![info exists :content-type]} {
      ${:object} set_property -new 1 ${:name} [:get_old_value]
      return
    }
    #:log "${:name}: got value '${:value}'"
    #${:object} set_property -new 1 ${:name} ${:value}
    
    set package_id [${:object} package_id]
    set entry_info [:entry_info]
    
    if {[:searchable]} {
      set publish_date_cmd {;}
      set save_flag ""
    } else {
      set publish_date_cmd {$file_object set publish_date "9999-12-31 23:59:59.0+01"}
      set save_flag "-use_given_publish_date true"
    }
    
    #
    # Make sure that we do not mis-interprete spaces in paths or file
    # names in the foreach loop.
    #
    if {[llength ${:content-type}] == 1} {
      set :tmpfile [list ${:tmpfile}]
      set :value [list ${:value}]
    }
    
    set revision_ids {}
    set newValue ""
    foreach content_type ${:content-type}  object_name [dict get $entry_info name]  tmpfile ${:tmpfile}  fn ${:value} {
    
          # Sanitize the filename
          regsub -all -- {\\+} $fn {/} fn  ;# fix IE upload path
          set fn [ad_file tail $fn]
          #
          # Set the value of the two flags in the command below in
          # case a more strict sanitizing is needed. With the settings
          # below, ad_sanitize_filename makes just sure the filename
          # does not contain invalid characters.
          #
          set fn [ad_sanitize_filename  -collapse_spaces=false  -tolower=false $fn]
    
          set file_object [:store_file  -file_name $fn  -content_type $content_type  -package_id $package_id  -parent_id [dict get $entry_info parent_id]  -object_name $object_name  -tmpfile $tmpfile  -publish_date_cmd $publish_date_cmd  -save_flag $save_flag]
    
          lappend revision_ids [$file_object revision_id]
          lappend newValue $fn
        }
    
    #
    # Update the value with the attribute value pair list containing
    # the revision_id. TODO: clear revision_id on export.
    #
    set newValue [list name $newValue revision_id $revision_ids]
    ${:object} set_property -new 1 ${:name} $newValue
    set :value $newValue
  • entry_info (scripted)

    if {${:multiple}} {
      if {[info exists :tmpfile]} {
        set list ${:tmpfile}
      } else {
        set list [:get_from_value ${:value} name]
      }
      set objName {}
      for {set i 0} {$i < [llength $list]} {incr i} {
        lappend objName file:${:name}___$i
      }
    } else {
      set objName file:${:name}
    }
    #:log ENTRY_INFO=[list name $objName parent_id [${:object} item_id]]
    return [list name $objName parent_id [${:object} item_id]]
  • get_from_value (scripted)

    #
    # The value of a form entry might be:
    # - an atomic list element
    # - a list with attribute value pairs
    #
    # This function tries to obtain the queried attribute from the
    # attribute value pair notation. If this fails, it returns a
    # default value.
    #
    set valueLength [llength $value]
    if {$valueLength > 1 && $valueLength % 2 == 0} {
      if {[dict exists $value $attribute]} {
        return [dict get $value $attribute]
      }
    }
    return [lindex $raw 0]
  • get_old_value (scripted)

    return [${:object} form_parameter __old_value_${:name} ""]
  • initialize (scripted)

    :type file
    set :booleanHTMLAttributes {multiple}
    set :widget_type file(file)
    next
  • label_or_value (scripted)

    if {[info exists :link_label]} {
      return [:localize [:link_label]]
    }
    return $v
  • link_label (setter)

  • multiple (setter)

  • no_value_provided (scripted)

    expr {${:value} eq ""}
  • pretty_value (scripted)

    if {$v ne ""} {
      set entry_info [:entry_info]
    
      set result ""
      foreach object_name [dict get $entry_info name] fn [:get_from_value $v name] {
    
        set item_info [${:object} item_ref  -default_lang [${:object} lang]  -parent_id [dict get $entry_info parent_id]  $object_name]
    
        #:log "name <$object_name> pretty value name '[dict get $item_info stripped_name]'"
    
        set l [::xowiki::Link new -destroy_on_cleanup  -page ${:object} -type "file"  -lang [dict get $item_info prefix]  -stripped_name [dict get $item_info stripped_name]  -label $fn  -extra_query_parameter [list [list filename $fn]]  -parent_id [dict get $item_info parent_id]  -item_id [dict get $item_info item_id]]
        append result [$l render]
      }
      return $result
    }
  • render_input (scripted)

    
    set package_id [${:object} package_id]
    set entry_info [:entry_info]
    set fns [:get_from_value ${:value} name ${:value}]
    
    #
    # The HTML5 handling of "required" would force us to upload in
    # every form the file again. To implement the sticky option, we
    # set temporarily the "required" attribute to false
    #
    if {${:required}} {
      set reset_required 1
      set :required false
    }
    #if {${:CSSclass} eq "form-control"} {
    #  append :CSSclass -file
    #}
    #
    # The following snippet for file-label tailoring is Bootstrap-only
    # and requires in non-bootstrap cases styling.
    #
    #if {[info exists :choose_file_label]} {
    #  ::html::label -for ${:id} -class "btn [::xowiki::CSS class btn-default]" {
    #    ::html::span -class upload-btn-label {
    #      ::html::t ${:choose_file_label}
    #    }
    #    set :CSSclass form-control-hidden
    #    next
    #  }
    #} else {
    #  next
    #}
    
    next
    
    ::html::t " "
    set id __old_value_${:name}
    ::html::div {
      ::html::input -type hidden -name $id -id $id -value ${:value}
    }
    ::html::div -class file-control -id __a$id {
      foreach  object_name [dict get $entry_info name]  revision_id [:get_from_value ${:value} revision_id ""]  fn $fns {
            #:msg "${:name}: [list :get_from_value <${:value}> name] => '$fn'"
            set href [::$package_id pretty_link -download 1  -parent_id [dict get $entry_info parent_id]  $object_name]
    
            if {![:istype image]} {
              append href ?filename=[ns_urlencode $fn]
              if {[nsf::is integer $revision_id]} {
                append href &revision_id=$revision_id
              }
            }
    
            if {[info exists reset_required]} {
              set :required true
            }
            ::html::div {
              ::html::a -href $href {::html::t [:label_or_value $fn] }
            }
          }
      #
      # Show the clear button just when
      # - there is something to clear, and
      # - the formfield is not disabled, and
      # - the form-field is not sticky (default)
      #
      set disabled [:is_disabled]
      if {${:value} ne "" && !$disabled && !${:sticky}} {
        #::html::input -type button -value [_ xowiki.clear] -id $id-control
    
        set del_id "$id-control"
        ::html::a -href "#"  -id $del_id  -title [_ xowiki.clear]  -class "delete-item-button" {
              html::t ""
            }
        template::add_event_listener  -id $id-control  -script [subst {document.getElementById('$id').value = ''; document.getElementById('__a$id').style.display = 'none';}]
    
      }
    }
  • reset_on_validation_error (scripted)

    #
    # Reset the value for form-fields of type "file" to empty to avoid
    # confusions in case of form validation errors. A file-name might
    # have been provided, but the file was not uploaded due to the
    # validation error. If we would not reset the value, the provided
    # name would cause an interpretation of an uploaded empty file.
    #
    #ns_log debug "reset_on_validation_error [:serialize]"
    set :value ""
  • searchable (setter)

  • size (setter)

  • sticky (setter)

  • store_file (scripted)

    
    set content_type_registered [::xo::dc get_value check_content_type {
      select case when exists
      (select 1 from cr_mime_types where mime_type = :content_type) then 1 else 0 end
      from dual
    }]
    #
    # If the provided mime type is not registered, or unknown, try
    # to look it up via the file extension.
    #
    if {!$content_type_registered
        || $content_type in { application/octetstream application/force-download }
      } {
      set content_type [::xowiki::guesstype $file_name]
      #
      # Here, the mime type could sill be an unknown/unregistered
      # one. We could check, whether this mime type is registered. If
      # not, we could add it on the fly or we could map it to the
      # registered unknown type (maybe via package parameter of
      # acs-content-repository + a new API call).
      #
    }
    
    set file_object [::$package_id get_page_from_name -name $object_name -parent_id $parent_id]
    if {$file_object ne ""} {
      #
      # File entry exists already, create a new revision
      #
      #:msg "new revision (value $file_name)"
      $file_object set import_file $tmpfile
      $file_object set mime_type $content_type
      $file_object set title $file_name
      eval $publish_date_cmd
      $file_object save {*}$save_flag
    } else {
      #
      # Create a new file
      #
      #:msg "new file"
      set package_id [${:object} package_id]
      set file_object [::xowiki::File new -destroy_on_cleanup  -title $file_name  -name $object_name  -parent_id $parent_id  -mime_type $content_type  -package_id $package_id  -creation_user [::xo::cc user_id] ]
      $file_object set import_file $tmpfile
      eval $publish_date_cmd
      #
      # When production_mode is set, make sure, the new file object
      # is not in a published state.
      #
      if {[::$package_id get_parameter production_mode:boolean 0]} {
        $file_object publish_status "production"
      }
      $file_object save_new {*}$save_flag
    }
    return $file_object
  • tmpfile (scripted)

    :set [self proc] $value
  • validator (setter)

  • value (scripted)

    if {[llength $args] == 0} {
      if {[:no_value_provided]} {
        return [:get_old_value]
      }
      return ${:value}
    }
    return [next]
  • viruscheck (setter)