GettingMarkupArguments

Note: The recipe on this page has been superseded by ParseArgs since PmWiki 2.0beta25.

Superceded -- see Cookbook:ParseArgs .

Question

How to get the arguments passed within a markup in an array.

Inspired by a question from Ben Wilson in the maillist:

I have a markup, such as: (:thismarkup key=value:)
And I want to pass the key=value to a function where the values can the be put into form fields. How can I pass the values?

Code was originally from Pm's PITS.php. The rest I picked up from the maillist.

Answer

Add a function to get the parameters and pass them back in an array. Put the code somewhere in your config.php:

 
function GetDirectiveArgs($args,$opt=array())
{
  # adopted from PITS.php 
  # parse passed string into single arguments
  # arg-format: results in:
  # "arg1"               $arg['arg1'] = 1
  # "+arg2"              $arg['arg2'] = 1
  # "-arg3"              $arg['arg3'] = 0
  # "arg4=string"        $arg['arg4'] = 'string'
  # "arg5=string_string" $arg['arg5'] = 'string string'
  #
  # default values can be passed in the second parameter (as an array)
  # sample call see below

  $terms = preg_split('/((?<!\\S)[-+]?[\'"].*?[\'"](?!\\S)|\\S+)/',
    $args,-1,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

  # @DEBUG(print_r($terms,true),1);

  foreach($terms as $t) {
    if (trim($t)=='') continue;
    if (preg_match('/([^\'":=]*)[:=]([\'"]?)(.*?)\\2$/',$t,$match))
      $opt[$match[1]] = str_replace("_"," ",$match[3]); 
    else
    {
      if (substr($t,0,1)=='-') 
        { $opt[substr($t,1)] = 0; }
      elseif (substr($t,0,1)=='+') 
        { $opt[substr($t,1)] = 1; }
      else
        { $opt[$t] = 1;  }
    }
  }

  return $opt;
}


Usage

for testing use

 (:testgetarg arg1 arg2=value2 arg3=value_with_virtual_blanks +arg4 -arg5 :)

in a wiki-page.

You also have to add the following code in your config.php (only for the test):

 
Markup('testgetarg','directives',
       '/\\(:testgetarg\\s*(.*?)\\s*:\\)/e',
       "TestGetArg(PSS('$1'))");

function TestgetArg($args)
{
  $opt['default'] = 'DEFAULT'; # set some default values ...
  $opt['arg1']    = 'DEFAULT ARG1'; # ... before calling the func
  $arglist = GetDirectiveArgs($args,$opt);
  echo "<pre>".print_r($arglist,true)."</pre>";
}

Discussion

The function will parse the passed parameterstring into single parameters and store it in an array.

The parameterstring is passed as the first argument to the function. In the second argument you can pass a array with preset values of each parameter to be exspected.

markup-arg-format:results in:
arg1$arg['arg1'] = 1
+arg2$arg['arg2'] = 1
-arg3$arg['arg3'] = 0
arg4=string$arg['arg4'] = 'string'
arg5=string_string$arg['arg5'] = 'string string'

Spaces within a passed parameter can be specified by underscores (_) (so you can't pass any underscores within a argument).

TestGetArg(PSS('$1'))
When using the /e option on the pattern match, it's a good idea in general to make sure that the replacement pattern is in double quotes, and that any parameters are passed to the PSS() function if they're likely to have quotes or backslashes in them.

possible improvements

  • implement a arg-format arg="string with real blanks" instead of using arg=string_with_virtual_blanks (see RegularExpressions? for ideas how to achieve this; see ParseArgs for a recipe that has this implemented).

Contributors

  • Pm (code was originally from his PITS)
  • KAL