xowiki::Package instproc resolve_page (public)

 <instance of xowiki::Package[i]> resolve_page \
    [ -use_package_path use_package_path ] [ -simple on|off ] \
    [ -lang lang ] object method_var

Defined in /var/www/openacs.org/packages/xowiki/tcl/package-procs.tcl

Try to resolve from object (path) and query parameter the called object (might be a package or page) and the method to be called.

Switches:
-use_package_path (optional, defaults to "true")
-simple (optional, boolean, defaults to "false")
when set, do not try to resolve using item refs, prototype pages or package_path
-lang (optional)
language used for resolving
Parameters:
object (required)
element name to be resolved (not an XOTcl object)
method_var (required)
output variable for method to be called on the object
Returns:
instantiated object (Page or Package) or empty

Testcases:
xowiki_test_cases, path_resolve
Source code:
upvar $method_var method

# get the default language if not specified
if {![info exists lang]} {
  set lang [:default_language]
  :log "no lang specified for '$object', use default_language <$lang>"
}
#:log "object '$object', default-lang $lang"

#
# First, resolve package level methods,
# having the syntax PACKAGE_URL?METHOD&....
#

if {$object eq ""} {
  #
  # We allow only to call methods defined by the policy
  #
  set exported [${:policy} defined_methods Package]
  foreach m $exported {
    #:log "--QP :exists_query_parameter $m = [:exists_query_parameter $m] || [:exists_form_parameter $m]"
    if {[:exists_query_parameter $m] || [:exists_form_parameter $m]} {
      set method $m  ;# determining the method, similar file extensions
      return [self]
    }
  }
}

if {[string match "//*" $object]} {
  #
  # We have a reference to another instance, we can't resolve this
  # from this package.  Report back not found by empty result.
  #
  #ns_log notice "reference to another instance: <$object>"
  return ""
}

#:log "--o object is '$object'"
if {$object eq ""} {
  #
  # We have no object, but as well no method callable on the
  # package If the method is "view", allow it to be called on the
  # root folder object.
  set m [:query_parameter m]
  if {$m in {list show-object file-upload}} {
    array set "" [list  name [::${:folder_id} name]  stripped_name [::${:folder_id} name]  parent_id [::${:folder_id} parent_id]  item_id ${:folder_id}  method [:query_parameter m]]
  } else {
    set object [${:id} get_parameter index_page:graph "index"]
    #:log "--o object after getting index_page is '$object'"
  }
}

#
# Second, resolve on object level, unless we have already an
# item_id from above.
#
if {![info exists (item_id)]} {
  array set "" [:item_info_from_url -with_package_prefix false -default_lang $lang $object]
  #:log "item_info_from_url returns [array get {}]"
}

#:log "object <$object>"
set fallback_languages [:get_parameter -check_query_parameter false fallback_languages ""]
if {$(item_id) == 0 && $fallback_languages ne ""} {
  foreach fallback_language $fallback_languages {
    if {$fallback_language ne $lang} {
      array set "" [:item_info_from_url -with_package_prefix false -default_lang $fallback_language $object]
      if { $(item_id) != 0 } {
        :log "item_info_from_url based on fallback_lang <$fallback_language> returns [array get {}]"
        break
      }
    }
  }
}

if {$(item_id) ne 0} {
  if {$(method) ne ""} { set method $(method) }
  if {![info exists method]} { set method "" }

  if {$method eq "download"} {
    set object_id $(item_id)
    set isObject [::xo::dc 0or1row -prepare integer check_object_id {
      select 1 from acs_objects where object_id = :object_id
    }]

    if {!$isObject} {
      #
      # Something horrible must have happened. We have a cached
      # item_id, which is not an object.
      #
      ns_log error "GN: BIG PROBLEM: the cache lookup of <$(parent_id)-$(name)> returned"  "something, which is not an object <$(item_id)>.. flush cache for this"
      xo::xotcl_object_type_cache flush -partition_key $(parent_id) $(parent_id-$(name)
      set parent_id $(parent_id)
      set name $(name)
      set fetched_id [::xo::dc get_value -prepare integer,text check_object_id {
        select item_id from cr_items where parent_id = :parent_id and name = :name
      }]
      ns_log notice "... refetched ID <$(parent_id)-$(name)> -> $fetched_id"
      set (item_id) $fetched_id
    }
  }
  try {
    :get_page_from_item_or_revision_id $(item_id)
  } on error {errorMsg} {
    ns_log error "GN: BIG PROBLEM 2: could not fetch page for item_id '$(item_id)' CONTEXT: [array get {}]"
    try {
      set cache_name [::nsf::dispatch xo::xotcl_object_type_cache cache_name $(item_id)]
      set cache_key $(parent_id)-$(name)
      set cache_value "NONE"
      set cached [ns_cache_get $cache_name $cache_key cache_value]
      set cache_info "cache_name $cache_name cache_key $cache_key cached $cached cache_value $cache_value"
      if {$cached} {
        xo::xotcl_object_type_cache flush -partition_key $(parent_id) $(parent_id)-$(name)
      }
    } on error {errorMsg} {
      set cache_info "no cache info <$errorMsg>"
    }
    ns_log notice "... cache info $cache_info"
    return -code error -errorcode $::errorCode -errorinfo $::errorInfo $errorMsg
  } on ok {result} {
    set page $result
  }
  try {
    set cache_name [::nsf::dispatch xo::xotcl_object_type_cache cache_name $(item_id)]
    set cache_key $(parent_id)-$(name)
    set cache_value "NONE"
    set cached [ns_cache_get $cache_name $cache_key cache_value]
    set cache_info "cache_name $cache_name cache_key $cache_key cached $cached cache_value $cache_value"
  } on error {errorMsg} {
    set cache_info "no cache info <$errorMsg>"
  }
  #ns_log notice "GOT <$page> cache info $cache_info"

  # TODO: remove me when settled
  if {[$page info vars storage_type] eq ""} {ad_log notice "$page has no storage_type"}

  if {[info exists (logical_package_id)] && [info exists (logical_parent_id)]} {
    #
    # If there was a logical_package_id provided from
    # item_info_from_url, we require that also a logical_parent_id
    # is required. In this case, change the context of the
    # resolved package to this page.
    #
    $page set_resolve_context -package_id $(logical_package_id) -parent_id $(logical_parent_id)
  }

  return $page
}

if {$simple} {
  return ""
}
#:log "NOT found object=$object"

# try standard page
set standard_page [${:id} get_parameter -check_query_parameter false $(stripped_name)_page]
if {$standard_page ne ""} {
  #
  # Allow for now mapped standard pages just on the top-level
  #
  set page [:get_page_from_item_ref  -allow_cross_package_item_refs false  -use_package_path true  -use_site_wide_pages true  -use_prototype_pages true  -default_lang $lang  -parent_id ${:folder_id}  $standard_page]
  #:log "--o resolving standard_page '$standard_page' returns $page"
  if {$page ne ""} {
    return $page
  }
  # Maybe we are calling from a different language, but the
  # standard page with en: was already instantiated.
  #set standard_page "en:$stripped_object"
  #set page [:resolve_request -default_lang en -path $standard_page method]
  #:msg "resolve -default_lang en -path $standard_page returns --> $page"
  #if {$page ne ""} {
  #  return $page
  #}
}

# Maybe, a prototype page was imported with language en:, but the current language is different
#if {$lang ne "en"} {
#  set page [:resolve_request -default_lang en -path $stripped_object method]
#  #:msg "resolve -default_lang en -path $stripped_object returns --> $page"
#  if {$page ne ""} {
#     return $page
#  }
#}

if {$use_package_path} {
  # Check for this page along the package path
  #:log "check along package path"
  foreach package [:package_path] {
    set page [$package resolve_page -simple true -lang $lang $object method]
    if {$page ne ""} {
      #:log "set_resolve_context inherited -package_id ${:id} -parent_id ${:folder_id}"
      $page set_resolve_context -package_id ${:id} -parent_id ${:folder_id}
      return $page
    }
  }
  #:log "package path done [array get {}]"
}

#
# The call ":lookup -use_site_wide_pages true" works for looking
# up the site-wide-pages all kind of packages, not only ::xowiki::Package
#
set (item_id) [:lookup -use_site_wide_pages true -name en:$(stripped_name)]
set page [expr {$(item_id) != 0 ? [:get_page_from_item_or_revision_id $(item_id)] : ""}]
#:log "get_site_wide_page for en:'$(stripped_name)' returned '$page' (stripped name)"
if {$page ne ""} {
  #:log "set_resolve_context site-wide -package_id ${:id} -parent_id ${:folder_id}"
  $page set_resolve_context -package_id ${:id} -parent_id ${:folder_id}
  return $page
}

#
# Is the current user allowed to create a page from the prototype
# pages?  In some packages, this might not be allowed.
#
if {[:check_permissions -package_id ${:id} [self] create-from-prototype]} {

  :log "try to import a prototype page for '$(stripped_name)' [array get {}]"
  if {$(stripped_name) ne ""} {
    #
    # Try to import of prototype pages into the actual folder.
    #
    if {[info exists (logical_parent_id)]} {
      set parent_id $(logical_parent_id)
    } elseif {[info exists (parent_id)]} {
      set parent_id $(parent_id)
    } else {
      set parent_id ${:folder_id}
    }
    set page [:www-import-prototype-page  -lang $lang  -parent_id $parent_id  -add_revision false  $(stripped_name)]
  }
  if {$page eq ""} {
    :log "no prototype for '$object' found"
  }
}

return $page
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: