Priority: Enhancement
Current State: Closed
Released In: 2.0.0
Target Release: major
Applies To: Engine
Component: Configure
Branches: trunk
Item 12140 ported the small patch from TWiki that enabled configure Types to declare makeChecker routine, thus enabling generic (item-independent) checkers.
Generic checkers are good because they reduce the effort of creating a checker for an item; make the checks for similar items consistent, reduce maintenance effort, and reduce the amount of code/number of modules that configure has to load.
The makeChecker mechanism is useful, but as I've been developing generic checkers, I discovered that we can do better.
This item upates configure to try harder to find a checker for an item. It also provides some infrastructure support for generic checkers. And some generic checkers.
The new method is to instantiate the first of:
- Item-specific checker:
{Key}{Key2}
... > =Configure/Checkers/Key/Key2/...
- Type-declared checker: if the
$type->can('makeChecker')
, whatever it provides
- Type-default checker:
- Map
ref( $type )
from Foswiki::Configure::Types::xxx
to Foswiki::Configure::Checkers::xxx
- If that checker exists, instantiate it. Otherwise:
- Consult the Type's
@ISA
. If mapping any of the ancestor types to Foswki::Configure::Checkers::xx
succceeds, instantatiate it. Otherwise:
- Recursively consult the ancestor Type's
@ISA
, instantiating the first checker that can be mapped.
- If we still can't find a checker, the item is unchecked.
The result of the
Type-default search is cached, so that it is done no more than once/Type (not item).
Note that we do not attempt to map when (if) the search arrives at
Foswiki::Configure::Type
. (no 's). Although we could map to
Foswki::Configure::Checker
,
that's really not useful.
Also note that this is backward compatible with all existing checkers.
With this change, all that's necessary to add a generic checker for a Type is to create the corresponding Checker.
For example:
- The checker for OCTAL is
Foswiki::Configure::Checkers::OCTAL
. Simply creating OCTAL.pm means that any OCTAL item (that doesn't have an Item-specific checker) will get Foswiki::Configure::Checkers:OCTAL
.
- If we don't create the OCTAL checker (we do, but for other reasons), such an OCTAL item will use the NUMBER checker, because the OCTAL Type inherits from NUMBER. (The theory is that if a Type inherits from another Type(s), the corresponding Checker is structured the same way.)
Generic checkers also benefit from some infrastructure support.
- The ability to parameterize generic checkers in the .spec file.
- This adds CHECK="parameter" syntax to the spec OPTIONs field. Generic checkers can use these to tailor their checks.
- For example, PATH CHECK="guess:data perms:rwpd filter:',v$'" CHECK="perms:r filter:'\\\\.txt$'" replaces the {DataDir} checker.
- Checker provides a parsing routine to turn the string into a list of hashes. This standardizes the option string syntax and makes using options easy.
- Syntax: option option:value option:value,value,value... option:"quoted-string"
- One hash per CHECK clause; all option values are arrayrefs.
- Parser support for FEEDBACK= items is along for the ride as its in the same place, harmless without the rest of FEEDBACK, and used by the generic checkers to determine whether FEEDBACK is enabled for an item.
- Methods to access an item's values without conjuring up an eval ($Foswiki::cfg$keys). (Many of which aren't error checked or have other issues.)
- $checker->getItemCurrentValue - Get the current (unexpanded) value of $checker's item (or specified item if {keys} passed.
- $checker->getItemDefaultValue - Get the default (unexpanded) value of $checker's item (or specified item if {keys} passed.
- $checker->setItemValue - Set the current value of $checker's item (or specified item if {keys} passed.
- guessMajorDir becomes a wrapper around guessDirectory - can guess directories relative to other {keys} and at any {key}{key} level.
Nothing (important) different happens to items with existing checkers until/unless the .spec file is updated. (And the existing, 'boring' checkers are deleted.)
Previously unchecked items will pickup the default checkers with default options (e.g. radix 10, no min or max value) for NUMBER, show expanded value, but no file checking or guessing for PATH, etc.
--
TimotheLitt - 31 Oct 2012
The new checkers turned up a issue in
UnitTestContrib where undefined fields were escaping into LSC.
I added defensive code to showExpandedValue to make this a visible error instead of a crash.
Thanks to George Clark for reporting the issue and helping to narrow it down.
--
TimotheLitt - 01 Nov 2012
Unfortunately undefined fields in LSC are by design. There are several examples "in the wild" where undefined is required. We could work around them, but the larger concern is what about private extensions, where we don't have access. For proper backwards compatibility, we really need to support undefined config variables.
-
{TempfileDir}
if undefined, gets set to a sane runtime value during Foswiki.cfg initialization, but if defined, overrides the system temp setting. Foswiki 1.2 handles it correctly, but if the LSC is used on a Foswiki 1.1 system, files end up in the root directory. Unit tests fail trying to write to /
- TopicInteractionPlugin defaults
$Foswiki::cfg{TopicInteractionPlugin}{WebDAVFilter}
to a long regular expression when undefined.
- MongoDBPlugin defaults $Foswiki::cfg{MongoDBPlugin}{query_timeout} to 2000, when it's undefined. The new code sets it to zero.
Support to "undefine" something that has been previously been defined might be nice, but at a minimum, a value undefined in a Spec file should not be written to the LSC unless the user intentionally modifies the displayed field.
--
GeorgeClark - 07 Nov 2012
Marking this waiting for release. The generic checkers are in place.
LocalSite.cfg could use some review, but that doesn't need to be on this task.
--
GeorgeClark - 18 Oct 2013