ProcessForm

Summary: Maintain values in fields and make PVs of the form name/values when a form is submitted
Version: 1.0
Prerequisites:
Status: Beta
Maintainer: Peter Bowers
Users: +1 (View / Edit)
Categories: Forms

Questions answered by this recipe

This section is optional; use it to indicate the types of questions (if any) this recipe is intended to answer.

When making a simple form (such as a data query or etc) which submits back on itself I want to make sure the input values are maintained between submissions. It would also be nice to have access to those values in the rest of the page through PVs.

Description

Add "processform" directive to maintain values between form submissions and create PVs from field values.

The directive (:processform [METHOD]:) can be placed anywhere in your form. It will ensure that your fields maintain values between submissions (assuming you have set up your form to submit to this page -- see below under "notes" for instructions). It will also create a PV (Page Variable) so that you can access the values set in your form fields via the {$name} syntax.

Installation

Simply copy this text into your local/config.php:


# This markup allows forms to automatically update $InputVals (to keep the same
# values displayed on the form between submissions) and $FmtPV (to allow use
# of those values in the rest of the page).  Argument can be "POST" for method
# post or anything else (nothing included) for get method.
Markup('ProcessForm', '<{$var}',
  '/\\(:processform\\s*(\\w*):\\)/e',
  "ProcessForm(\$pagename, strtoupper('$1'))");
function ProcessForm($pagename, $method)
{
    global $InputValues, $FmtPV;
    if ($method == "GET")
        $method_array = $_GET;
    else
        $method_array = $_POST;
    foreach ($method_array as $k=>$v) {
       $foo = htmlspecialchars($v,ENT_NOQUOTES);
       # This keeps the field values current with the form from submission to
       # submission, but has nothing to do with PTV
       $InputValues[$k] = $foo;
       # Single quotes cause havoc in pmwiki.php (line 754 eval in 2.2.0 Beta65)
       # unless they are escaped with \.  This line escapes any unescaped single
       # quote and turns any existing escapes into double-escapes.
       $foo = preg_replace('/\\\\/', '\\\\\\\\\\\\', $foo);
       $foo = preg_replace("/(?<!\\\)'/", "\'", $foo);
       $foo = preg_replace("/\&quot;/", '"', $foo);
       # This creates a Page Variable for use in the rest of the page
       $FmtPV['$'.$k] = "'$foo'";
    }
    return('');
}

NOTE: See alternate code below for an important modification suggested by HansB.

Then on the page with your form simply add the (:processform:) markup. If you are using method=POST in your form then that is the default and you don't need to specify it for processform. If you are using method=GET in your form then specify that as (:processform GET:).

That's all there is to it.

Notes

This is not specific to this recipe, but if you want more instructions on how to make a query form or etc that submits onto itself, here you go...


(:input form method=GET:)
(:input hidden n {*$FullName}:)

(:input submit submit "Submit":)

If you would like to see an example that demonstrates the use of this recipe's markup then try cut/pasting this text into a page (after installing according to the above instructions), put a value in the text box, and then submit and watch what happens...


(:processform GET:)
(:input form method=GET:)
(:input hidden n {*$FullName}:)

(:input text name=mytext size=100:)

(:input submit mysubmitname "My Button Label":)

It seems like you want to talk about {$mytext}.  Tell me more.
(:input end:) 

Hmmm... Just came across a function parse_str() in PHP. Looks like it might do all this job in one or 2 steps...


CodeGier 2017, Oct. 28th: I tested the example and figured out this missing line: (:input end:)


HansB pointed out something I didn't know about forms -- they can post to arrays. Obviously my code above does not handle this, and this is the code Hans gave me as working in this situation:

 foreach ($method_array as $k=>$val) {
     if (is_array($val)) {
         foreach ($val as $i=>$v)
           $InputValues[$k][$i] = htmlspecialchars($v,ENT_NOQUOTES);
     }
     else $InputValues[$k] = htmlspecialchars($val,ENT_NOQUOTES);
  }

I don't have time right at this point to merge this code up into mine and test it so I'm assuming if you need arrays then you can figure out what needs to be merged to make this work. (NOTE: If somebody else wants to merge it in and test it and then modify this page I am not picky about "ownership"...)

(Hans:) The snippet above will set $InputValues, but not the $FmtPV page variables. Some array methos needs to be applied for this as well. OR much simpler don't use input arrays and avoid errors by excluded any with this snippet 9adding an extra line to Peter's original code above:

foreach ($method_array as $k=>$v) {
    if (!is_array($v))
       $foo = htmlspecialchars($v,ENT_NOQUOTES);

Release Notes

If the recipe has multiple releases, then release notes can be placed here. Note that it's often easier for people to work with "release dates" instead of "version numbers".

See Also

HttpVariables for another way to get access to the $_GET/$_POST values from within your page.

InputDefault -- see (:input default request=1:) for another way to maintain field values between submissions.

Contributors

Cookbook.InputDefault gives largely the same solution, but on a per-page basis.

Comments

User notes +1: 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.