Skip to content

Commit

Permalink
Item14237: Added validation of spec options.
Browse files Browse the repository at this point in the history
  • Loading branch information
vrurg committed Dec 7, 2016
1 parent 0edc420 commit fbf5494
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 28 deletions.
2 changes: 1 addition & 1 deletion UnitTestContrib/test/unit/ConfigTests.pm
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ around tear_down => sub {
sub test_getNode {
my $this = shift;

$this->app->cfg->tieData;
$this->app->cfg->specsMode;

my $node = $this->app->cfg->getKeyNode('ConfigTests.SubKey1.Key2');

Expand Down
1 change: 1 addition & 0 deletions core/lib/Foswiki/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,7 @@ sub _arg2keys {
return () if @_ < 1;

if ( @path == 1 ) {
return () unless defined $path[0];
if ( ref( $path[0] ) ) {
Foswiki::Exception::Fatal->throw(
text => "Reference passed is not an arrayref but "
Expand Down
26 changes: 19 additions & 7 deletions core/lib/Foswiki/Config/DataHash.pm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ package Foswiki::Config::DataHash;

use Assert;
use Foswiki::Exception;
use Foswiki ();

use Foswiki::Class qw(app);
extends qw(Foswiki::Object);
Expand Down Expand Up @@ -167,6 +168,8 @@ sub TIEHASH {

my $this = $class->new( @profile, @_ );

Foswiki::load_class(NODE_CLASS);

return $this;
}

Expand Down Expand Up @@ -359,14 +362,24 @@ accessors. The nuances could be caused by the ways Moo works with attributes.
=cut

sub makeNode {
my $this = shift;
my $key = shift;
my $this = shift;
my $key = shift;
my %profile = @_;

my $nodes = $this->nodes;
my $node;
my $node = $nodes->{$key};
my $section;

my $invalidAttr = &NODE_CLASS->invalidSpecAttr( keys %profile );
$section = $node ? $node->section : ( $profile{section} // undef )
if $invalidAttr;
Foswiki::Exception::Config::BadSpecData->throw(
text => "Unknown spec attribute '$invalidAttr' found",
key => $this->app->cfg->normalizeKeyPath( [ $this->fullPath, $key ] ),
( defined $section ? ( section => $section ) : () ),
) if $invalidAttr;

if ( defined $nodes->{$key} ) {
my %profile = @_;
if ($node) {

$node = $nodes->{$key};

Expand Down Expand Up @@ -439,10 +452,9 @@ Creates a new =Foswiki::Config::Node= object using =@nodeProfile=.
=cut

sub createNode {
my $orig = shift;
my $this = shift;

return $orig->( $this, NODE_CLASS, parent => $this, @_ );
return $this->create( NODE_CLASS, parent => $this, @_ );
}

=begin TML
Expand Down
115 changes: 100 additions & 15 deletions core/lib/Foswiki/Config/Node.pm
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,6 @@ has value => (

=begin TML
---+++ ObjectAttribute default
Node's default value as defined by spec.
=cut

has default => (
is => 'rw',
predicate => 1,
);

=begin TML
---+++ ObjectAttribute parent
Parent container object of class =Foswiki::Config::DataHash=.
Expand Down Expand Up @@ -110,9 +97,73 @@ Defines if this is a leaf node, or branch, or type of this node is undefined yet
=cut

has isLeaf => ( is => 'rw', );
has isLeaf => ( is => 'rw', builder => 'prepareIsLeaf', );

=begin TML
---++ Spec option attributes
The following object attributes are valid spec options.
=cut

=begin TML
---+++ ObjectAttribute default
Node's default value as defined by spec.
=cut

has default => (
is => 'rw',
predicate => 1,
builder => 'prepareDefault',
);

=begin TML
---+++ ObjectAttribute type
Key data type like _NUMBER_ or _TEXT_.
=cut

has type => ( is => 'rw', predicate => 1, builder => 'prepareType', );

=begin TML
---+++ ObjectAttribute label
Text label attached to the config key.
stubMethods qw(prepareParent prepareSection prepareValue);
=cut

has label => ( is => 'rw', predicate => 1, builder => 'prepareLabel', );

=begin TML
---+++ Empty prepare methods
The following methods are empty initializers of their respective attributes:
* prepareParent
* prepareSection
* prepareValue
* prepareDefault
* prepareIsLeaf
* prepareLabel
These methods do nothing but could be overriden by subclasses.
=cut

stubMethods qw(prepareParent prepareSection prepareValue prepareDefault
prepareIsLeaf prepareLabel);

my @validSpecAttrs = qw(
default type label isLeaf
);

=begin TML
Expand Down Expand Up @@ -159,6 +210,40 @@ sub getValue {

=begin TML
---+++ ClassMethod invalidSpecAttr(@attrList) -> $attrName
Returns first invalid spec attribute found in the list. Returns undef otherwise.
This method is dual: it is class and object method at the same time.
=cut

my $attrRx = '(?:' . join( '|', @validSpecAttrs ) . ')';

sub invalidSpecAttr {
my $class = shift;

foreach my $attr (@_) {
return $attr unless $attr =~ /^$attrRx$/;
}

return;
}

=begin TML
---+++ ObjectMethod prepareType -> 'TEXT'
Initializer of =type= attribute.
=cut

sub prepareType {
return 'TEXT';
}

=begin TML
---+++ ObjectMethod _trigger_value
Trigger method of =value= attribute.
Expand Down
10 changes: 5 additions & 5 deletions core/lib/Foswiki/Exception/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ has key => (
predicate => 1,
builder => 'prepareKey',
);
has specObject => (
has nodeObject => (
is => 'rw',
predicate => 1,
);
Expand All @@ -46,16 +46,16 @@ around stringify => sub {
sub prepareSection {
my $this = shift;

if ( $this->has_specObject ) {
return $this->specObject->section;
if ( $this->has_nodeObject ) {
return $this->nodeObject->section;
}
}

sub prepareKey {
my $this = shift;

if ( $this->has_specObject ) {
return $this->specObject->fullName;
if ( $this->has_nodeObject ) {
return $this->nodeObject->fullName;
}
}

Expand Down

0 comments on commit fbf5494

Please sign in to comment.