Catalyst::Plugin::OrderedParams - Maintain order of submitted form parameters


Catalyst-Plugin-OrderedParams documentation Contained in the Catalyst-Plugin-OrderedParams distribution.

Index


Code Index:

NAME

Top

Catalyst::Plugin::OrderedParams - Maintain order of submitted form parameters

SYNOPSIS

Top

    use Catalyst;
    MyApp->setup( qw/OrderedParams/ );

DESCRIPTION

Top

This plugin enables handling of GET and POST parameters in an ordered fashion. By default in Catalyst, form parameters are stored in a simple hash, which loses the original order in which the parameters were submitted. This plugin stores parameters in a Tie::IxHash which will retain the original submitted order.

One particular application for this plugin is email handlers, where you want the output of your email to reflect the order of form elements in the form.

Simply add this plugin to your application and the following code will be in the proper order.

    for my $param ( $c->req->param ) {
        $email .= $param . ": " . $c->req->param( $param );
    }

CAVEATS

Top

Note that technically according to RFC2388, the ordering of fields submitted by a form does not have to follow the order of the form elements displayed on the page. However, I believe most, if not all, common browsers do follow this convention. This plugin has been tested with both IE6 and Firefox 1.0.6.

SEE ALSO

Top

Catalyst

AUTHOR

Top

Andy Grundman, <andy@hybridized.org>

THANKS

Top

Tom Shinnick, shenme@perlmonks.org, for pointing out RFC2388.

COPYRIGHT

Top


Catalyst-Plugin-OrderedParams documentation Contained in the Catalyst-Plugin-OrderedParams distribution.

package Catalyst::Plugin::OrderedParams;

use strict;
use NEXT;
use Tie::Hash::Indexed;

if ( Catalyst->VERSION ge '5.49' ) {
    require HTTP::Body;
}

our $VERSION = '0.06';

sub prepare_request {
    my $c = shift;
    
    # make sure the params hash hasn't already been touched by another plugin
    if ( scalar keys %{ $c->req->{parameters} } ) {
        $c->log->error( "OrderedParams: Request parameters have already been "
            . "set/modified.  Please load the OrderedParams plugin "
            . "before all other plugins." );
    }
    else {
        my $params = {};
        tie %{$params}, 'Tie::Hash::Indexed';
        $c->req->{parameters} = $params;

        if ( Catalyst->VERSION ge '5.49' ) {
            my $query_params = {};
            tie %{$query_params}, 'Tie::Hash::Indexed';
            $c->req->{query_parameters} = $query_params;
        }
    }

    return $c->NEXT::prepare_request(@_);
}

sub prepare_body {
    my $c = shift;
    
    return $c->NEXT::prepare_body(@_) if Catalyst->VERSION lt '5.49';
    
    # due to complex interactions in 5.5 this method has to be overridden
    # instead of extended.
    
    if ( defined $c->request->{_body} ) {
        # We may not have a body to process if it was a GET request
        return if !ref $c->request->{_body};

        # have we already built the object?
        return if defined $c->request->{_body}->{ordered};
    }

    # for 5.5+, we create a new HTTP::Body instance with indexed hashes.
    my $length = $c->req->header('Content-Length') || 0;
    my $type   = $c->req->header('Content-Type');
    my $body   = HTTP::Body->new( $type, $length );
    
    tie %{ $body->{param}  }, 'Tie::Hash::Indexed';
    tie %{ $body->{upload} }, 'Tie::Hash::Indexed';
    $body->{ordered} = 1;
   
    $c->req->{_body} = $body;

    # Initialize on-demand data
    $c->engine->prepare_body( $c, @_ );
    $c->prepare_parameters;
    $c->prepare_uploads;

    if ( $c->debug && keys %{ $c->req->body_parameters } ) {
        my $t = Text::SimpleTable->new( [ 37, 'Key' ], [ 36, 'Value' ] );
        for my $key ( sort keys %{ $c->req->body_parameters } ) {
            my $param = $c->req->body_parameters->{$key};
            my $value = defined($param) ? $param : '';
            $t->row( $key,
                ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
        }
        $c->log->debug( "Body Parameters are:\n" . $t->draw );
    }    
}

1;
__END__