Feature Proposal: Collection of problems with Foswiki::Func that we should address

Motivation

Extensions to Foswiki::Func and associated classes exposed to extensions authors (see DevelopingPlugins for a list of the affected classes) These are entirely extensions to the interface and should not impact existing extensions (other than to allow a subset of them to remove back-doors into the core)

Note to implementors; if you implement any of the functions described here, then add unit tests and document properly or your work will be reverted. Foswiki::Func is a critical interface, and absolutely must be engineered professionally. Once a function has been documented in this topic for at least 14 days and has also been implemented in the trunk, then remove it from this topic so we can track open proposals without excessive noise.

Description and Documentation

Foswiki::Func was designed in the days before subwebs, and has not really moved with the times. It has been patched, glued, and gently massaged but has never had a whole-body makeover.

We're not proposing that here, because it should wait for an "OO Plugins" API. However what we can do right now is spot some of the more obvious holes and plug them. At the moment this is a feature request list, starting with those features needed for a recent implementation of Filesys::Virtual::Foswiki, a filesystem interface intended to be layered on top of the Foswiki store (and reflecting Foswiki semantics)

green indicates proposed changes. red indicates a problem or concern.

List subwebs

There is no way to get a list of subwebs in a web. This is because the getListOfWebs function ignores the second $web parameter to Store::getListOfWebs Solution: pass the $web parameter on, change the spec to:

---+++ getListOfWebs( $filter [, $web [, $norecurse]] ) -> @webs

  • $filter - spec of web types to recover
Gets a list of webs, filtered according to the spec in the $filter, which may include one of:
  1. 'user' (for only user webs)
  2. 'template' (for only template webs i.e. those starting with "_")
$filter may also contain the word 'public' which will further filter out webs that have NOSEARCHALL set on them. 'allowed' filters out webs the current user can't read.
  • $web if undef, the function returns the list of root webs. If it is set to a valid web name, returns a list of the subwebs of that web.
  • $norecurse if set will suppress the default behaviour, which is to list all subwebs in the hierarchy. If $norecurse is set, will only return the webs immediately under $web (or the root webs if $web is undef) irrespective of the setting of $Foswiki::cfg{EnableHierarchicalWebs}.
Return: list of qualified web names, expressed relative to the $web (or the root if $web is undef). '/' is used as the separator for subwebs. In the case of an error, returns an empty list.

Type-tests on attachments

DONE Tasks.Item1441 Right now it's impossible to type-test an attachment. This is a fairly fundamental operation for anyone trying to get info about an attachment.

No way to open a stream on an attachment or topic

DONE Tasks.Item1441 This can be important when you are working with very large attachments, where reading the entire attachment is just stupid. Two types of open are require, open-read and open-write (optional append).

Get rest url

Return a url like with getScriptUrl, but for the rest handlers. We plan to introduce rest handlers as the default way to speak to plugins, so we need this to be defined as an API call, to be later able to change the structure of the link. i coul also think about just enhancing the current getScriptUrl with this special case.

getRestUrl( $web, $topic, $plugin, $handlerName [,%params]) -> $url

  • $web/$topic ..
  • $plugin name of the plugin, which is used to call the rest handler
  • $handlerName name of the rest handler
  • %params optional named parameters to be added to the URL e.g. gift1=>'gold', gift2=>'frankincense'
->Return : url as a string e.g. /bin/rest/DBConnectorPlugin/editfield?topic=System.WebHome;wysiwyg=1

What's the motivation for not using getScriptUrl? It seems to me this could be done with a simple documentation fix... -- CrawfordCurrie - 26 Mar 2009

getPubUrl / getPubUrlPath

Foswiki::Func::getPubUrl() should call Foswiki::getPubUrl, and pass parameters like $absolute - just returning the Foswiki::cfg is way too naive. It appears that {PubUrlPath} can be set to an absolute url - but that there are corners (mostly in plugins) where this doesn't work just right.

and then we can deprecate getPubUrlPath, which is a subset of getPubUrl().

getRestUrl( $web, $topic, $plugin, $handlerName) -> $url

  • $web/$topic: ..
  • $plugin: name of the plugin, which is used to call the rest handler
  • $handlerName: name of the rest handler
->Return : as full url as a string e.g. /bin/rest/DBConnectorPlugin/editfield?topic=System.WebHome

This is insufficient documentation. No spec of getPubUrl. Looks like you pasted the wrong doc. -- CrawfordCurrie - 26 Mar 2009

More flexible registered tags

Too often, plugins have to resort to commonTagsHandler because the tag cannot easily be written using the %TAG% format. Examples include rendering extensions like ExplicitNumberingPlugin, multi-line block-oriented tags like the <dot> </dot> blocks used in DirectedGraphPlugin, ToolTipPlugin, which uses a registeredTag that assumes but doesn't validate that there is a begin-tag / end-tag block relationship.

registerRegexTagHandler( 'regex', \&_handler )

For example, to process DOT blocks:
 
registerRegexTagHandler( '<DOT(.*?)>(.*?)<\/DOT>', \&_handleDot($2,$1) )     

and to handle the ### syntax for explicit numbering;

registerRegexTagHandler( '(^---+\+*)(\#+)([0-9]*)', $1.&makeHeading(length($2), $3) );     
registerRegexTagHandler( '\#\#(\w+\#)?([0-9]+)?\.(\.*)([a-zA-Z]?)', &makeExplicitNumber($1,$2,length($3),$4)) ;

I am dead set against this, because it takes the tag parser where it was never designed to go. Extending TML is definitely not something we should be doing using the tag parser. -- -- CrawfordCurrie - 26 Mar 2009

ALERT! NOTE: You are very welcome to extend the list above, but please add solutions and not just problems.

Clean up log interface

There is now a cleaner implementation of logging in the core, but it isn't exposed to extensions. Propose publishing the interface supported by the Foswiki::Logger class.

log($level, @fields)

Adds a log message to a log.

  • $level - level of the event - one of debug, info, warning, error, critical, alert, emergency.
  • @fields - an arbitrary list of fields to output to the log. These fields are recoverable when the log is enumerated using the eachEventSince function.
The levels are chosen to be compatible with Log::Dispatch.

eachEventSince($time, $level) -> $iterator

  • $time - a time in the past
  • $level - log level to return events for.
Get an iterator over the list of all the events at the given level between $time and now.

Events are returned in oldest-first order.

Each event is returned as a reference to an array. The first element of this array is always the date of the event (seconds since the epoch). Subsequent elements are the fields passed to log.

Note that a log implementation may choose to collapse several log levels into a single log. In this case, all messages in the same set as the requested level will be returned if any of the collapsed levels is selected.

-- CrawfordCurrie - 26 Mar 2009

Discussion

I thought the CGI object e.g. is not present on FSA? So using FSA would break the plugins, or? -- EugenMayer - 26 Jan 2009

Actually the getCgiQuery should be deprecated in favor of a new getRequestObject, with the same idea (but notice that a Foswiki::Request is not a CGI object [currently it is, but this must change in the future]) -- GilmarSantosJr - 27 Jan 2009

True, and I added that new function above, replacing getUrlparam. The interface to the FSA request object is, to all intents and purposes, identical to the interface to a CGI object.

-- CrawfordCurrie - 27 Jan 2009

This release process has turned into anarchy lately.

This feature proposal is originally not a feature proposal but an old Codev discussion topic that someone gave the proposal form.

And there is no committed developer and no date of commitment. And yet developers that know better have started implementing the features on trunk.

There is no respect around our process anymore. How will new developers joining be motivated to raise feature proposals and follow the process when the old school devs do not care at all?

I am sure there is nothing wrong with the features added and they would most likely pass through the process with no fuzz. May we may miss some important feedback when people have to see this topic by chance and assume that as long as there is no committed developer added the discussion is just at brain storm level.

-- KennethLavrsen - 21 Mar 2009

The granularity of the release process is too coarse for the API changes described here. At the same time, we can't handle them as individual Enhancements in Tasks because they would be invisible. So we're compromising, and using this topic to attract comments. The implementations are also done by different people, so "committed developer" doesn't make sense. I have moved the state to "Under Construction" to reflect the curious dual nature of this "feature request".

-- CrawfordCurrie - 26 Mar 2009

Proposal is not a feature; rejected in favour of individual tasks.

-- CrawfordCurrie - 17 Feb 2012
Topic revision: r19 - 17 Feb 2012, CrawfordCurrie
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy