File Coverage

blib/lib/Dancer/Plugin/Deferred.pm
Criterion Covered Total %
statement 24 52 46.1
branch 0 8 0.0
condition 0 19 0.0
subroutine 8 13 61.5
pod n/a
total 32 92 34.7


line stmt bran cond sub pod time code
1 2     2   965951 use 5.008001;
  2         8  
  2         92  
2 2     2   14 use strict;
  2         4  
  2         71  
3 2     2   13 use warnings;
  2         4  
  2         140  
4              
5             package Dancer::Plugin::Deferred;
6             # ABSTRACT: Defer messages or data across redirections
7             our $VERSION = '0.003'; # VERSION
8              
9 2     2   12 use Carp qw/croak/;
  2         11  
  2         121  
10 2     2   12 use URI;
  2         3  
  2         57  
11 2     2   4119 use URI::QueryParam;
  2         1556  
  2         63  
12              
13 2     2   13 use Dancer ':syntax';
  2         4  
  2         14  
14 2     2   2530 use Dancer::Plugin;
  2         2984  
  2         1627  
15              
16             my $conf;
17              
18             register 'deferred' => sub {
19 0     0     my ( $self, $key, $value ) = plugin_args(@_);
20 0   0       $conf ||= _get_conf();
21              
22 0           my $id = _get_id();
23              
24             # message data is flat "dpd_$id" to avoid race condition with
25             # another session
26 0   0       my $data = session( $conf->{session_key_prefix} . $id ) || {};
27              
28             # set value or destructively retrieve it
29 0 0         if ( defined $value ) {
30 0           $data->{$key} = $value;
31             }
32             else {
33 0 0         $value = var( $conf->{var_keep_key} ) ? $data->{$key} : delete $data->{$key};
34             }
35              
36             # store remaining data or clear it if no deferred messages are left
37 0 0         if ( keys %$data ) {
38 0           session $conf->{session_key_prefix} . $id => $data;
39 0           var $conf->{var_key} => $id;
40             }
41             else {
42 0           session $conf->{session_key_prefix} . $id => undef;
43 0           var $conf->{var_key} => undef;
44             }
45              
46 0           return $value;
47             };
48              
49             # destructively return all keys
50             register 'all_deferred' => \&_get_all_deferred;
51              
52             sub _get_all_deferred {
53 0   0 0     $conf ||= _get_conf();
54 0           my $id = _get_id();
55 0   0       my $data = session( $conf->{session_key_prefix} . $id ) || {};
56 0 0         unless ( var $conf->{var_keep_key} ) {
57 0           session $conf->{session_key_prefix} . $id => undef;
58 0           var $conf->{var_key} => undef;
59             }
60 0           return $data;
61             }
62              
63             register 'deferred_param' => \&_get_deferred_param;
64              
65             sub _get_deferred_param {
66 0     0     my ($arg) = @_;
67 0   0       $conf ||= _get_conf();
68 0           var $conf->{var_keep_key} => 1;
69 0           return ( $conf->{params_key} => var $conf->{var_key} );
70             }
71              
72             hook 'before_template' => sub {
73             my $data = shift;
74             $conf ||= _get_conf();
75             $data->{ $conf->{template_key} } = _get_all_deferred();
76             };
77              
78             hook 'before' => sub {
79             $conf ||= _get_conf();
80             my $id = params->{ $conf->{params_key} };
81             var( $conf->{var_key} => $id )
82             if $id;
83             };
84              
85             hook 'after' => sub {
86             my $response = shift;
87             $conf ||= _get_conf();
88             if ( var( $conf->{var_key} ) && $response->status =~ /^3/ ) {
89             my $u = URI->new( $response->header("Location") );
90             $u->query_param( _get_deferred_param() );
91             $response->header( "Location" => $u );
92             }
93             };
94              
95             # not crypto strong, but will be stored in session, which should be
96             sub _get_id {
97 0   0 0     $conf ||= _get_conf();
98 0   0       return var( $conf->{var_key} )
99             || sprintf( "%08d", int( rand(100_000_000) ) );
100             }
101              
102             sub _get_conf {
103             return {
104 0           var_key => 'dpdid',
105             var_keep_key => 'dpd_keep',
106             params_key => 'dpdid',
107             session_key_prefix => 'dpd_',
108             template_key => 'deferred',
109 0     0     %{ plugin_setting() },
110             };
111             }
112              
113             register_plugin for_versions => [ 1, 2 ];
114              
115             1;
116              
117              
118             # vim: ts=2 sts=2 sw=2 et:
119              
120             __END__