PageVariableExtensions

Summary: Functional extensions to page variables
Version: 20061029
Status: Obsolete
Prerequisites: pmwiki-2.1.5
Maintainer:

Questions answered by this recipe

I've found the page variables very useful but I can't only rely on their plain values, I need to be able to manipulate them.

This recipe is *officially* deprecated by MarkupExprPlus and would not be maintained anymore --Dfaure September 13, 2007, at 03:49 AM

Note: Much of this functionality can be done with core methods provided in the latest 2.1.xbeta series (see the See Also: below)

How may I have my own?

Description

The extendvars.phpΔ script enhances the variable features in several ways, providing markup and suffixes functions to dynamically initialize and manipulate their values:

  • The recipe provides the (:set ...:) markup directive to initialize/assign page variables.
  • The general syntaxic form for variables becomes {pagename$variable:function arg ...}, where the function is applied to the variable's value before returning it to the page.

As a preliminary sample, on a page where {$Name} renders as PageVariableExtensions, you may write:

(:set msg='{$Name:toupper} is here!':)
''oyez, oyez, {$msg}''
oyez, oyez, PAGEVARIABLEEXTENSIONS is here!.

Installation

Proceed to installation steps as usual for cookbook recipe scripts.

Warnings/Preliminary notes

User-defined page variables are very volatile things and only "page-local" and "page-wide" variables may be assigned with the (:set ...:) directive. Therefore:

  • Variable's values can only be seen from within the page they have been assigned (page-local aspect).
  • Conditional markup is ignored during value assignation (which occurs before):
(:set var='nice':)
(:if false:)(:set var='weird':)(:if:)
"Conditionals are {$var}"

"Conditionals are weird"

...instead of "Conditionals are nice" (page-wide aspect).

Variable initialization

The (:set var1=value1 var2=value2 ...:) markup directive allows the definition of new variables, including using ones previously defined earlier in the same directive, as in:

(:set 1stname=Dominique:)
(:set surname=Faure user='{$1stname} {$surname}':)
Hello, I'm {$user}
Hello, I'm Dominique Faure

During variable assignation, the directive is also able to recognize specific helper functions. The generic value syntax is

 '(=function arguments) params' (square brackets are also allowed).

The build-in helper functions include:

Helper function Usage
'(=if condition) value_if_TRUE "value if FALSE"'
Conditional assignation:

The condition itself is handled as other PmWiki conditional expressions. Please refer to conditional markup for further details.

Each value may be quoted in order to be interpreted as a single value.

The "value if FALSE" parameter is optional.

'(=time H=... M=... S=... d=... m=... Y=...)'
'(=time specification reference)'
Timestamp assignation:

The timestamp could be either defined from each of its constituting parts (omitted parts default to their current value according to the local date and time), or an US English formated date specification that would be parsed into a Unix timestamp (the number of seconds since January 1 1970 00:00:00 GMT), relative to the reference given, or the current time if none is supplied.

Please refer to the related PHP manual page for more details: mktime, strtotime.

'(=http_get name) default_value'
'(=http_post name) default_value'
'(=http_request name) default_value'
'(=http_cookie name) default_value'
'(=session_data name) default_value'
Interpage assignation:

The name argument would refers to GET, POST, COOKIE or SESSION values provided to the page as request parameters, cookie values or session data.
An optional default_value may be provided when name isn't available.

The revisited conditional is then

(:set flag=1 mood='(=if equal {$flag} 1) "nice" "weird"':)
"Conditionals are {$mood}"
"Conditionals are nice"

Variables could also be erased/removed with the (:set -VarToForget ...:) syntax.

Variable values manipulation functions

The following function suffixes are available to manipulate values as PmWiki renders them with the page text:

FunctionUsage
lenReturns the length of the string.
tolowerReturns string with all alphabetic characters converted to lowercase.
toupperReturns string with all alphabetic characters converted to uppercase.
ucfirstCapitalizes the 1st character if it is alphabetic.
revReverses the string.
rot13Performs the ROT13 encoding.
The ROT13 encoding simply shifts every letter by 13 places in the alphabet while leaving non-alpha characters untouched.
sub start lengthReturns the portion of string specified by the start and length parameters.
If start is non-negative, the returned string will start at the start'th position in string, counting from zero. For instance, in the string 'abcdef', the character at position 0 is 'a', the character at position 2 is 'c', and so forth.
If start is negative, the returned string will start at the start'th character from the end of string.
If length is given and is positive, the string returned will contain at most length characters beginning from start (depending on the length of string). If string is less than or equal to start characters long, nothing will be returned.
If length is given and is negative, then that many characters will be omitted from the end of string (after the start position has been calculated when a start is negative).
If start denotes a position beyond this truncation, an empty string will be returned.
CAUTION: negatives values must be enclosed between quotes as in '-42'.
(i)str whatstr returns all from the first occurrence of what to the end of the string.
istr is the case-insensitive variant.
(i)replace what withreplace returns a string with all occurrences of what replaced with the given with value.
ireplace is the case-insensitive variant.
(gm)ftime fmtftime returns a string formatted according to fmt from any timestamp (noticeably from the one provided by the {$Now} variable). Month and weekday names and other language dependent strings respect the current locale. gmftime behaves the same except that the time returned is Greenwich Mean Time (GMT).
See strftime and gmstrftime PHP functions for further references.
fdate fmtReturns a string formatted according to fmt from any yyyy-mm-dd or yyyymmdd given date. See strftime PHP function for further references.
regmatch patternReturns true or false if the value matches to the regular expression given in pattern.
regreplace pattern replacementSearches for matches to pattern and replaces them with replacement.
+ value
- value
* value
/ value
Enables arithmetic computations with numeric values.
asspacedReturns a spaced string as it is already done for the page name in the {$Namespaced} variable.
aspagename groupReturns a pagename (optionally relative to group).
aswikiReturns a WikiWord from a space-separated string of words.

Function calls may be chained as in: {$Namespaced:tolower:replace ' ' '_'} (which would provides: page_variable_extensions if triggered as the first sample).

Variable values may be provided as function parameters using angle brackets, as in:

(:set var='abcdef' s1=2 s2=4:)
* {$var:sub <$s1> 3}
* {$var:sub <$s2> 3}
  • cde
  • ef

Miscellaneous

As another workaround to the volatile nature of the user defined page variables (cf. preliminary note), the $EnableUrlSetVar flag (set to 1, before including the recipe script) would allow one to define variables from an url with parameters like ?set_var1=value1&set_var2=value2&..., as in:

[[{$PageUrl}?set_VarSetFromUrl=This the value|Go to page with a value set]]

Nota: You should prefer use the http_... variable initializers, which provide a more powerful control and doesn't need the $EnableUrlSetVar flag set.

Two extra directives are available to set/erase cookie values and/or session data:

 
(:cookie name=... value=... expire=... path=... domain=...:)

(:session var1=value1 var2=value2 -removedVar ...:)
  • The cookie directive takes account of the $CookiePrefix configuration option.
  • When ommitted, cookie path defaults to '/'.

Technical hints (advanced user/admin.)

You may easily extend the recipe providing your own functions in your local configuration files to initialize variables from specific data-sources or manipulate variable's values. Please refer to the recipe source code itself for live samples:

Variable initializers are defined in the $PageVarSetters array with the following prototype:

$PageVarSetters['...']($pagename, $func, $param, $default)
$PageVarSetters is an array of functions, indexed by name. These functions get called to initialize variables using their parameters or the provided default value:
  • $pagename - The name of the current page.
  • $func - The function name which initiated the call.
  • $param - The parameters provided in the call.
  • $default - The default value provided in the call.

Variable functions are defined in the $PageVarFuncs array, an indexed by name array of evaluable expression strings. Function parameters and current variable value are made available in the $funcparm array and the $value variable. The string evaluation should result in the replacement text.

Contributors

Dfaure

See Also

Release Notes

  • 2006-05-04 Initial release.
  • 2006-05-18 Allowed variables initialization from url parameters. Added (some) missing strftime date mapping for Win32.
  • 2006-06-28 Introduced conditional assignation, function parameters passing and regular expression functions.
  • 2006-07-07 Revamped assignation with helper functions, added arithmetic and wiki names functions.
  • 2006-07-10 Corrected cookie/session handling bugs.
  • 2006-07-13 Small function parsing bug fix. Added timestamp assignation.
  • 2006-09-28 Made recipe PmWiki 2.2.0-beta? compatible.
  • 2006-10-29 Added RecipeInfo data.

Comments

2006-05-17, Daniel
the fdate-function is perfect for me. I want to use it to generate the title according the page-name. but there is a problem: {$Name:fdate %d.%b %G} returns 19.Feb
The year is missing. If I delete the space between G the year appears. In the php-documentation I can't find any parameter for space, only for tab. Does anybody have an idea? Thanks!

the fdate function takes a format string parameter which must be enclosed with quotes if it contains spaces, then: {$Name:fdate '%d.%b %G'} would provide 19.Feb 2006. You may also have to use the last version to have %G handled on Win32. --Dfaure

Thank you! The ability to use links to allow readers to make selections that will change the values of variables that are used by conditional markup is great. For the benefit of anyone who may need to see some of this spelled out in more detail, I wrote out a step by step instruction using a basic show/hide function as an example and added it an earlier proof of concept page called NestedText. Of course, if what you really want is just a show hide function, you should take a look at the Show Hide recipe, which uses java script, but the show hide function was used as an easy example. In fact, in some situations, even some basic show hide solutions might require this recipe (Page Variable Extensions) in order to overcome some basic limitations of the Show Hide: dependent on java and uses divs, which can't be nested, making it very hard to add a show all and hide all function, see here for more detail. Pico June 29, 2006, at 05:07 PM

The new version looks great. I would like to define cookie (and session) variables (and values) from user input (urls). Can you offer any advice or suggestions? At first glance, it looks like this is what I would have to do:

  1. "set" a (page-local) variable using UrlSetVar, for example: ?set_sVar1=''value1'
  2. use a cookie (or session) directive to transfer the value, for example: (:cookie cVar1=:) or (:session sVar1=:)
  3. condition step 2 on step 1 (to prevent cookie and session variables from being cleared, for example (:if ! sVar1="":) (:cookie cVar1={$sVar1}:)
    Does that make sense? Is there a better way to do this? Thanks Pico July 07, 2006, at 12:01 PM

I would write something like:

(:set cVar1='(=http_cookie Var1)' Var1='(=http_get Var1) {$cVar1}':)
...
(:cookie name="Var1" value="{$Var1}" expire="{$Now:+ 3600}":)
  1. The Var1 variable gets the ?Var1=... url parameter, defaulting to the cookie defined cVar1 value.
  2. Use {$Var1} as requested,
  3. Then save it as a cookie named accordingly.
    --Dfaure

Is there some simple way to extend the list of helper functions? Hopefully they are entries in an array so that one could put an entry into a local/config.php that said something like the line below, so as to allow for a {$PageSpaced:myhelper} statement. StirlingWestrup July 07, 2006

You almost guessed it right. See the Technical hints above. --Dfaure

Is there any way to get this to work inside pagelists? I've found a use for {=$FullName:toupper} inside a custom pagelist format, but it doesn't seem to work.

I've managed to get it working inside a pagelist. I have a custom WordCount recipe that sets the number of words in a page to $Words. I've used it, in conjunction with this recipe to create a pagelist to list all of the chapters of a story, with a total wordcount at the bottom. The chapters are called StoryName-01, StoryName-02, etc. If you're having trouble getting {=$FullName:toupper} to work, you may need to do something like (:set PageName="{=$FullName}":){$PageName:toupper}. Here's my working format below, in case it helps.

[[#titlecounttotal]]
(:set totalwords='(=if equal "{<$Group}" "") 0 "{$totalwords}"':)
* [[{=$FullName}|{=$Title}]] ({=$Words} words)
(:set totalwords='{$totalwords:+ {=$Words}}':)
(:if equal {>$Group}:)

->Total: {$totalwords} words(:if:)
[[#end]]
(:pagelist fmt=#titlecounttotal group=Stories name=StoryName-* :)

It seems to me that the correct syntax for addition should be something like (:set x=1:)(:set x={$x:+1}:); I would expect {$x} would yield '2', but I get '1' - what am I doing wrong? Very exciting once I get it to work!

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.