Feature Proposal: URLPARAM should be able to validate the browser input

Motivation

Currently URLPARAM can only encode the results. It would be better if the macro could specify specific validation rules in the form of a regular expression that returns the legal content.

Description and Documentation

Add validate="regular_expression" to the URLPARAM macro. If provided, URLPARAM expands to the (match) param with the regular expression.

The macro would expand to the text matching within the ( ).
  • If nothing matches, or the () is missing from the validate, the macro would return the default.
  • If the regex has a compile error the param would throw an error.

It might be worth considering adding some simple keyword validations as well:
  • BOOLEAN: Uses core isTrue evaluation
  • NUMERIC:
  • ...

Implementation should also investigate any way to borrow from the Configure::Checkers:: style checker and specifications. For example NUMBER:min:1 max:1000

Examples

%URLPARAM{"enable" validate="BOOLEAN"}%
Expands as 0 or 1, using Foswiki::Func::isTrue()
%URLPARAM{"limit" validate="NUMERIC"}%
Throws error if input is not numeric. $ %URLPARAM{"foo" validate="REGEX:^([0-9a-f]+)$"}%: Returns empty string or only hex digits.

One use case would be in the JQueryLoader page, which expands

... effect:'%URLPARAM{"effect" default="fade"}%' ...

The "effect" is documented as effect: the effect used when showing the loaded content; possible values are: show, fade, slide, blind, clip, drop, explode, fold, puff, pulsate, highlight

 

The validated URLPARAM would be changed to:
effect:'%URLPARAM{"effect" default="fade" validate="(show|fade|slide|blind|...)}%'

Impact

%WHATDOESITAFFECT%
edit

Extensions using this new feature would not be compatible with Foswiki 1.x. It should degrade cleanly though, as the validate parameter would be ignored.

Implementation

-- Contributors: GeorgeClark - 02 Nov 2015

Discussion

As I get in to the implementation and borrowing code from the Configure checkers, I'm settling on the following syntax

Handler Check options Return
BOOLEAN
(none )
Returns 0 or 1, output of Foswiki::isTrue()
NUMBER
min:n max:n integer real float base:octal/decimal/hex
Throw oops if failed
STRING
min:n max:n accept:(regex) reject:(regex)
min, max & reject throw oops, accept filters
DATE
zone:utc/local raw
Normalize to Foswiki date unless raw. Throw error for invalid dates
-- Main.GeorgeClark - 18 Nov 2015 - 05:09

This isn't far enough along to merge into 2.1. Defer to 2.2.

-- GeorgeClark - 06 Dec 2015

What confuses me here is that in cases where a param is used more than once it's meaning won't change over each use. Yet more, in many cases same param might have same meaning for several topics and thus have same validator applicable. Does it mean one would need to copy/paste the validate parameter all over? What if a vlidator has to be changed at some point – shall we manually change the validator everywhere then?

It also comes to my mind that sometimes parameters are bundled together. A group of them might as well have same meaning at several places.

In my view parameters are better be checked once before any other topic processing is done. It shall be possible to have their validators grouped together and be accessible to %INCLUDE{}% in order to make it possible to define them once and use anywhere.

-- VadimBelman - 16 Dec 2015

We had some good discussion in the IRC channel. here. Some of the points discussed:
  • There are 3 possible outcomes of a validation:
    • Throw an "oops",
    • Return an inline error,
    • Record the error for report elsewhere.
  • If an error is not returned inline, then the default should be expanded if available
  • A topic could reference the same param in multiple places.
    • With "oops" or "report", then only one really needs the validations.
  • Validations are not global, they'd be local only to the particular macro instance.
  • Applications may want to gather all the validations in one place, for ex, in a topic to be included
    • A macro which only does validation, and reports inline would be useful.
    • %URLVALIDATE{"param" validate="the validation rule" format=" * $param - $error"}%
  • URLPARAM with "report" option will collect errors and report them in a %URLREPORT% macro.
This was an accepted proposal, but because of additional input and spec changes, re-opening it.

-- GeorgeClark - 17 Dec 2015

What we didn't clearly stated and it's not obvious from the latest changes is following: in neither case invalid param should be used. It means: if record-for-report is choosen and no default to use – then it's a oops or inline-error situation.

And I don't think that URLVALIDATE should not be allowed to oops. Why not, actually?

Otherwise we may finally get what could be recommended as the good practice.

-- VadimBelman - 17 Dec 2015

I think this can be reduced to just some additional parameters on URLPARAM and avoid extra macros, and add some useful features.
%URLPARAM{"name"}%
Default operation, returns the value of "name"
%URLPARAM{"name" format="$value" default="defaultvalue"}%
Returns value of "name", or the default value.
%URLPARAM{"name" format="Some string using $value"}%
Incorporate $value in the string, only if present. Used for conditional rendering of $value rather than relying on %IF type conditional rendering.
%URLPARAM{"name" validate="validation" fail="oops" }%
Failed validation causes an Oops.
%URLPARAM{"name" validate="validation" fail="inline" }%
Failed validation returned with inline alert, otherwise return the value.
%URLPARAM{"name" validate="validation" fail="report" format="   * $name $error"   }%
Report failed validations, otherwise return nothing. Useful in %INCLUDE% blocks for common validations.

-- GeorgeClark - 17 Dec 2015

Maybe "report" isn't the right word. What about fail="only"? Only generate output upon failure, otherwise macro is just removed.

-- GeorgeClark - 18 Dec 2015

Still obscure. But if fail is renamed to on_fail – then it sounds more meaningful:

on_fail="report"

-- VadimBelman - 18 Dec 2015

More suggestions after IRC discussion. Still require a way to collect errors and report them all either in a conditional div, or in a single oops for the collected errors.

-- Main.GeorgeClark - 18 Dec 2015

Adding my own "concern" as this proposal needs more work before it is implementable.

-- GeorgeClark - 20 Mar 2016

Changing to a Parked proposal.

-- GeorgeClark - 18 Feb 2017
 
Topic revision: r16 - 18 Feb 2017, GeorgeClark
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