Feature Proposal:

Motivation

This proposal comes from analysis of the requirements of the SitePermission page, as discussed in Tasks.Item2394. Thinking about that problem made me realise there may be something more generally useful in there.

SitePermissions enumerates per web. In each web, showing the DENYWEB and ALLOWWEB settings for that web. The values used by the access checking code can be determined using $meta->getPreference() where $meta is a web object (known in the code as a "web preference".

This requires some sort of general mechanism that will "expand this macro in another context". This would return the value of a macro as it would be if the current topic (web) were something else. For example, if I'm editing topic "ThisTopic" and I write %EXPAND{"$percntFLURB$percnt" scope="ThatTopic"}% it would return the value of FLURB as if "ThatTopic" were the current topic. scope would default to the current web.topic, so this makes this doubly interesting, since it supports delayed expansion.

Description and Documentation

EXPAND{"expression" scope="topictoexpandin" ...}%

Expands macros in expression as if they were used in the topic topictoexpandin. The viewer must have VIEW access to topictoexpandin for this to work. All the standard formatting macros can be used in expression, such as $percnt and $quot.

%EXPAND can be useful when you want to pick up the value of macros defined in another topic. For example, you might want to define a set of preferences in one topic, but pick up their value in another topic (this is very useful when building reusable applications). In this case you can write:
   * Set MYPREFERENCE = value
in "SettingsTopic" and then, in "MyTopic", write:
%EXPAND{"$percntMYPREFERENCE$percnt" scope="SettingsTopic"}%
Of course we can also write:
%EXPAND{"$percntMYPREFERENCE$percnt" scope="%OTHERTOPIC%"}%
which lets us select which other topic to get the preference value from.

Additional parameters can be passed to the macro being expanded using the standard macro syntax in the name of the macro; for example,

= EXPAND failed - no such topic 'SettingsTopic' =

Notes:
  • %EXPAND is not very efficient, and should be used sparingly.
  • To expand a web preference (for example, a web access control) then set scope="Theotherweb.%WEBPREFSTOPIC%"

Implementation

The implementation is straightforward - a new macro implementation in the Macros dir, 30 lines or so. I have tested it as described above, and it works beautifully.

-- Contributors: CrawfordCurrie - 20 Jan 2010

Discussion

please don't overload the keyword context to mean a topic.

and we ought to work out a param to mean output 'X' if the Setting / macro does not exist, and what to show if the user doesn't have permission to that web/topic

also, what fun - expand a macro in a different topic's context, but as its a setting expand to that topic's web preferences rather than the current topic's web preferences, and then :}

-- SvenDowideit - 20 Jan 2010

I can see the value expanding TML in a different scope (probably better term than context). The above pattern to motivate %EXPAND to get the value of a pref value defined in a different topic is quite common and already solvable using different means, e.g. SetVariablePlugin's %GETVAR. This is also related to SettingAndGettingVariablesUsingMacros where we will implement %SET and %GET macros. The latter could easily be extended by adding a topic parameter.

So all it needs is a somewhat better example to motivate %EXPAND that illustrate its usefulness and uniqueness ... that it definitely has. I just can't come up with a better example myself right now.

-- MichaelDaum - 20 Jan 2010

There is a minor discrepancy between the Motivation and the Description and Documentation. The Motivation has %EXPAND{"FLURB" topic="ThatTopic"}% whereas the Description and Documentation has %EXPAND{"$percntMYPREFERENCE$percnt" context="SettingsTopic"}%

There are two similar alternatives: %SEARCH and %INCLUDE
  • %SEARCH{search="." type="regex" topic="ThatTopic" format="<insert TML here>" nonoise="on"}% - but with %EXPAND, the TML is evaluated as if in ThatTopic
  • %INCLUDE{"ThatTopic" section="SomeSection TML="<insert TML here>"}% - but %EXPAND can evaluate TML in the context/scope of another topic without needing an %INCLUDE-able section.

%EXPAND would give topic="OtherTopic" capability to all macros (including those provided by plugins, and via the EasyMacroPlugin) that do not have built-in topic parameters. This is useful to users, and it allows for simpler plugins.

%EXPAND and HereDocumentSyntaxForMacros would be a powerful combination.

I would like to suggest a rev option, so that TML could be expanded as if in any specific revision of any arbitrary topic.

-- MichaelTempest - 20 Jan 2010

Sven, dead right; all I can suggest is wrapping the macro reference in a %IF. Because expand expands an arbitrary string rather than a single macro, it's not well placed to insert default values. I have changed context to scope. At the moment, errors are reported as string returns (not even using foswikiAlert )

Michael, yes, there are plugins that do this kind of thing (perhaps). Yes, it's related to SET and GET, with the difference that EXPAND works on an arbitrary string, expanding all macros in it in a different context, so is unlike GET in that respect.

While the rev option is on the face of it attractive, the preferences code has no support for building a preference DB based on old revs of topics, so it is far from a low-hanging fruit.

I'm checking this in for you to play with.

-- CrawfordCurrie - 20 Jan 2010

Since you have already committed it on SVN I assume you are a committed developer so I added your name and todays date so it gets listed in the 14 day rule list.

With the changes already made I support this feature.

On the documentation part maybe one more example will help its use. That is an easy thing to do once we get a little used to it.

This feature for sure fills a gap in the core that people have had for years.

-- KennethLavrsen - 20 Jan 2010
Topic revision: r8 - 11 Mar 2010, 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