-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi Oliver,
I think this is a great idea!
Thanks a lot.
Thomas
Oliver Tappe schrieb:
> Hi there,
>
> attached is a function I have found useful in some of the OTRS-modules I
> worked on recently. It is called CheckParams() and its purpose is to offer an
> intuitive and flexible way of checking the params-hash that has been passed
> into a method.
>
> Currently, many methods contain code like this:
>
> # check all needed objects
> foreach (qw(ConfigObject LogObject DBObject TimeObject MainObject)) {
> die "Got no $_" if (!$Self->{$_});
> }
>
> plus more checks for additional parameters that must be passed in via
> the %Params hash.
>
> When using CheckParams, the code looks like this:
>
> # check all needed objects
> CheckParams($Self, sub {
> 'ConfigObject' => '!Class=Kernel::Config',
> 'DBObject' => '!Class=Kernel::System::DB',
> 'LogObject' => '!Class=Kernel::System::Log',
> 'MainObject' => '!Class=Kernel::System::Main',
> 'TimeObject' => '!Class=Kernel::System::Time',
> });
>
> As you can see, you pass CheckParam() the hash-ref that shall be checked and
> a
> specification (for performance reasons this should always be an anonymous
> subroutine). In the specification, you simply declare the supported
> parameters, whether or not they are required (!) or optional (?) or if they
> have to be of a specific class (Class=...).
>
> CheckParams() supports checking of more complex data structures, too:
>
> CheckParams($Params, sub {
> 'GeneralAttrs' => {
> 'From' => '!',
> 'To' => '!',
> },
> 'JobAttrs' => {
> 'Creator' => '!',
> 'Changes' => [
> {
> 'Action' => 'm{^(create|change|delete|sync)$}',
> 'Path' => '!',
> 'Content' => '?',
> }
> ],
> }
> });
>
> This code snippet makes sure that the given $Params-hash contains two
> elements
> (GeneralAttrs & JobAttrs), each of which has to follow the specified
> substructures.
>
> As I believe this function could be useful throughout OTRS (now that we have
> the 2.2-branch), I'd like to add it to the framework. I can see two ways of
> doing that:
>
> 1.) non-OO style: add some kind of helper module (e.g. Utils.pm) and add
> CheckParams() as a *function* to that.
> 2.) OO style: add a new module Utils/Params.pm which contains a
> *class-method*
> Check(), such that you'd have to invoke it like this
> Utils::Params->Check($Params, sub {
> ...
> });
>
> So what do you think? Do you like the idea in general at all? If so, how
> should that functionality be integrated (OO- or non-OO-style)?
>
> Please fire any suggestions or questions to this list or directly my way.
>
> cheers,
> Oliver
>
>
> ------------------------------------------------------------------------
>
> =item CheckParams()
>
> Utility function that can be used by any method that accepts param-hashes
> to check if the given parameters actually match the expectations.
>
> Each individual parameter has a specification that describes the expectation
> that the calling function has towards this param. The following specifications
> are supported:
>
> * '!' - the parameter is required
> * '?' - the parameter is optional
> * 'm{regex}' - the parameter must match the given regex
> * '!Class=...' - the parameter is required and must be an object of the given
> class
> * '?Class=...' - if the parameter has been given, it must be an object of the
> given class
>
> The function will confess for any unknown, missing, or non-matching param.
>
> =cut
>
> sub CheckParams
> {
> my $Params = shift or confess('need to pass in params-hashref!');
> my $ParamsSpec = shift or confess('need to pass in params-spec-hashref
> (or -sub)!');
>
> # TODO: allow to switch off this function via configuration in production
> # environments, as it is rather heavy
>
> # fetch param-spec from function, if that has been given:
> if (ref($ParamsSpec) eq 'CODE') {
> $ParamsSpec = $ParamsSpec->();
> }
>
> # print a warning for any unknown parameters that have been given:
> my @UnknownParams
> = grep { !exists $ParamsSpec->{$_}; }
> keys %$Params;
> if (@UnknownParams) {
> my $UnknownParamsStr = join ',', @UnknownParams;
> confess("Enocuntered unknown params: '$UnknownParamsStr'!\n");
> }
>
> # check if all required params have been specified:
> foreach my $Param (keys %$ParamsSpec) {
> my $Spec = $ParamsSpec->{$Param};
> if (ref($Spec) eq 'HASH') {
> # Handle nested specs by recursion:
> my $SubParams = $Params->{$Param};
> if (!defined $SubParams) {
> confess("Required param '$Param' is missing!");
> }
> CheckParams($SubParams, $Spec);
> }
> elsif (ref($Spec) eq 'ARRAY') {
> # Handle nested spec arrays by looped recursion:
> my $SubParams = $Params->{$Param};
> if (!defined $SubParams) {
> confess("Required param '$Param' is missing!");
> }
> elsif (ref($SubParams) ne 'ARRAY') {
> confess("Value for param '$Param' must be an array-ref!");
> }
> foreach my $SubParam (@$SubParams) {
> CheckParams($SubParam, $Spec->[0]);
> }
> }
> elsif ($Spec eq '!') {
> # required parameter:
> if (!exists $Params->{$Param}) {
> confess("Required param '$Param' is missing!");
> }
> }
> elsif ($Spec =~ m{^\!Class=(.+)$}i) {
> my $Class = $1;
> # required parameter ...
> if (!exists $Params->{$Param}) {
> confess("Required param '$Param' is missing!");
> }
> # ... of specific class
> if (!$Params->{$Param}->isa($Class)) {
> confess("Param '$Param' is not a '$Class', but that is
> required!");
> }
> }
> elsif ($Spec eq '?') {
> # optional parameter - nothing to do
> }
> elsif ($Spec =~ m{^\?Class=(.+)$}i) {
> my $Class = $1;
> # optional parameter ...
> if (exists $Params->{$Param}) {
> # ... of specific class
> if (!$Params->{$Param}->isa($Class)) {
> confess("Param '$Param' is not a '$Class', but that is
> required!");
> }
> }
> }
> elsif ($Spec =~ m{^m{(.+)}$}) {
> # try to match given regex:
> my $Regex = $1;
> my $Value = $Params->{$Param};
> if ($Value !~ m{$Regex}) {
> confess("Required param '$Param' isn't matching regex
> '$Regex' (given value was '$Value')!");
> }
> }
> else {
> # complain about unknown spec:
> confess("Unknown param-spec '$Spec' encountered!");
> }
> }
>
> return scalar 1;
> }
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> OTRS mailing list: dev - Webpage: http://otrs.org/
> Archive: http://lists.otrs.org/pipermail/dev
> To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/dev
- --
((otrs)) :: OTRS GmbH :: Europaring 4 :: D - 94315 Straubing
Fon: +49 (0) 9421 56818 0 :: Fax: +49 (0) 9421 56818 18
http://www.otrs.com/ :: Communication with success!
Geschäftsführer: André Mindermann
Handelsregister: HRB 9452 Bad Homburg
Steuernummer: 003/240/97521
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org
iD8DBQFG6RNm5VEHpl41kC8RAjs/AJwJxS/7WT0DFvW2lnhzW0HfM90H4QCg53Md
7KDeKDBtOAzb6/hy7glajrc=
=WCAg
-----END PGP SIGNATURE-----
_______________________________________________
OTRS mailing list: dev - Webpage: http://otrs.org/
Archive: http://lists.otrs.org/pipermail/dev
To unsubscribe: http://lists.otrs.org/cgi-bin/listinfo/dev