line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package JQuery::DataTables::Request; |
2
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
112683
|
use 5.012; |
|
4
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
166
|
|
4
|
4
|
|
|
4
|
|
21
|
use strict; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
120
|
|
5
|
4
|
|
|
4
|
|
26
|
use warnings; |
|
4
|
|
|
|
|
14
|
|
|
4
|
|
|
|
|
150
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.109'; # VERSION |
8
|
|
|
|
|
|
|
|
9
|
4
|
|
|
4
|
|
35
|
use Carp; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
467
|
|
10
|
|
|
|
|
|
|
|
11
|
4
|
|
|
4
|
|
24
|
use base 'Class::Accessor'; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
4028
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
JQuery::DataTables::Request - represents a DataTables server-side request |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 SYNOPSIS |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my $dt_req = JQuery::DataTables::Request->new( client_params => $client_parameters ); |
20
|
|
|
|
|
|
|
if ( $dt_req->column(0)->{searchable} ) { |
21
|
|
|
|
|
|
|
# do something |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
$dt_req->search->{value}; # the global search value |
25
|
|
|
|
|
|
|
if ($dt_req->search->{regex}) { |
26
|
|
|
|
|
|
|
# global search is set to regex |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# find the column definition with the name 'col_name' |
30
|
|
|
|
|
|
|
my $cols = $dt_req->find_columns( by_name => 'col_name' ); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
$dt_req->draw; #sEcho or draw parameter |
33
|
|
|
|
|
|
|
$dt_req->start; #iDisplayStart or start parameter |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 DESCRIPTION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This module represents a DataTables server-side request originating from the DataTables |
38
|
|
|
|
|
|
|
client side JS library. There are two major versions of DataTables(v1.9 and v1.10) that send |
39
|
|
|
|
|
|
|
differently named parameters server-side for processing. This module only provides an API |
40
|
|
|
|
|
|
|
that corresponds to the v1.10 parameters but maps the v1.9 parameters to the corresponding v1.10 |
41
|
|
|
|
|
|
|
parameters. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
The DataTable parameters are documented at the following locations: |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=over |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=item L |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item L |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=back |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Each column parameter is represented as a HashRef like so: |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
{ |
56
|
|
|
|
|
|
|
name => 'col_name', |
57
|
|
|
|
|
|
|
data => 'col_name', |
58
|
|
|
|
|
|
|
orderable => 1, |
59
|
|
|
|
|
|
|
searchable => 1, |
60
|
|
|
|
|
|
|
search => { |
61
|
|
|
|
|
|
|
value => 'search string', |
62
|
|
|
|
|
|
|
regex => 0, |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
e.g. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
$dt_req->column(0)->{search}{value} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Order parameters look like this: |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
{ |
73
|
|
|
|
|
|
|
dir => 'asc', |
74
|
|
|
|
|
|
|
column => 1 |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
e.g. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$dt_req->order(0)->{dir} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
The order and column accessors are indexed the same way as your column parameters so |
82
|
|
|
|
|
|
|
C<< $req->column(0) >> returns the column in the client_params C<[columns][0]> column. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
C is similar in that C<< $req->order(0) >> returns the C parameter data. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head1 METHODS |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=cut |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# V1.10 accessors |
91
|
|
|
|
|
|
|
__PACKAGE__->mk_accessors(qw( |
92
|
|
|
|
|
|
|
draw |
93
|
|
|
|
|
|
|
start |
94
|
|
|
|
|
|
|
length |
95
|
|
|
|
|
|
|
search |
96
|
|
|
|
|
|
|
_version |
97
|
|
|
|
|
|
|
_order |
98
|
|
|
|
|
|
|
_columns |
99
|
|
|
|
|
|
|
) |
100
|
|
|
|
|
|
|
); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 new |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Creates a new JQuery::DataTables::Request object. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $dt_request = JQuery::DataTables::Request->new( client_params => \%parameters ); |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Accepts the following parameters |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=over |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=item client_params |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
This is a HashRef that should contain your DataTables parameters as provided by the DataTables |
115
|
|
|
|
|
|
|
JS library. Any parameters provided that are not recognized as DataTables request are silently ignored. |
116
|
|
|
|
|
|
|
Usually, whatever framework you are using will already have a way to convert these parameters |
117
|
|
|
|
|
|
|
to a HashRef for you, (e.g. C<< $c->req->parameters >> in a Catalyst app) |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=back |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
new will confess/croak on the following scenarios: |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=over |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item client_params is not provided |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=item client_params is not a HashRef |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item client_params isn't recognized as containing DataTables parameters |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=back |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
You should catch these if you are worried about it. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=cut |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# client_params should be hashref |
138
|
|
|
|
|
|
|
sub new { |
139
|
6
|
|
|
6
|
1
|
1983
|
my ($class, %options) = @_; |
140
|
|
|
|
|
|
|
|
141
|
6
|
50
|
|
|
|
24
|
confess 'No DataTables parameters provided in the constructor - see client_params option' |
142
|
|
|
|
|
|
|
unless defined($options{'client_params'}); |
143
|
|
|
|
|
|
|
|
144
|
6
|
50
|
|
|
|
26
|
confess 'client_params must be a HashRef' |
145
|
|
|
|
|
|
|
unless ref($options{'client_params'}) eq 'HASH'; |
146
|
|
|
|
|
|
|
|
147
|
6
|
|
|
|
|
18
|
my $obj = bless {}, __PACKAGE__; |
148
|
|
|
|
|
|
|
|
149
|
6
|
|
|
|
|
26
|
my $version = $obj->version( $options{client_params} ); |
150
|
6
|
100
|
100
|
|
|
50
|
if (defined $version && $version eq '1.10') { |
|
|
100
|
66
|
|
|
|
|
151
|
3
|
|
|
|
|
17
|
$obj->_process_v1_10_params( $options{'client_params'} ); |
152
|
|
|
|
|
|
|
} elsif (defined $version && $version eq '1.9') { |
153
|
2
|
|
|
|
|
10
|
$obj->_process_v1_9_params( $options{'client_params'} ); |
154
|
|
|
|
|
|
|
} else { |
155
|
1
|
|
|
|
|
238
|
confess 'client_params provided do not contain DataTables server-side parameters (i.e. this is not DataTables request data)'; |
156
|
|
|
|
|
|
|
} |
157
|
5
|
|
|
|
|
37
|
$obj->_version( $version ); |
158
|
5
|
|
|
|
|
52
|
return $obj; |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=head2 column |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
my \%column = $request->column(0); |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Returns a single column definition of the requested index |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub column { |
170
|
6
|
|
|
6
|
1
|
1246
|
my ($self,$idx_arr) = @_; |
171
|
6
|
50
|
|
|
|
17
|
return if !defined($idx_arr); |
172
|
6
|
|
|
|
|
17
|
return $self->_columns->[$idx_arr]; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head2 columns |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
my \@columns = $request->columns([0,1]); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Returns column definitions for the requested indexes. Can accept either an |
180
|
|
|
|
|
|
|
arrayref of scalars or a single column scalar. If no column index is provided |
181
|
|
|
|
|
|
|
all columns are returned. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=cut |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub columns { |
186
|
9
|
|
|
9
|
1
|
968
|
my ($self, $idx_arr) = @_; |
187
|
9
|
|
|
|
|
25
|
my $col_ref = $self->_columns; |
188
|
9
|
100
|
|
|
|
109
|
return $col_ref if !defined($idx_arr); |
189
|
|
|
|
|
|
|
|
190
|
3
|
100
|
|
|
|
19
|
$idx_arr = [ $idx_arr ] if ref($idx_arr) ne 'ARRAY'; |
191
|
|
|
|
|
|
|
|
192
|
3
|
|
|
|
|
6
|
my $ret_arr; |
193
|
3
|
|
|
|
|
13
|
foreach my $idx ( sort @$idx_arr ) { |
194
|
5
|
|
|
|
|
21
|
push(@$ret_arr, $col_ref->[$idx]); |
195
|
|
|
|
|
|
|
} |
196
|
3
|
|
|
|
|
15
|
return $ret_arr; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head2 columns_hashref |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Get all column definitions as a Hashref, with the column index as the key |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=cut |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub columns_hashref { |
206
|
1
|
|
|
1
|
1
|
3
|
my ($self) = @_; |
207
|
1
|
|
|
|
|
2
|
my %col_hash; |
208
|
1
|
|
|
|
|
2
|
@col_hash{ 0 .. $#{$self->_columns} } = @{$self->_columns}; |
|
1
|
|
|
|
|
12
|
|
|
1
|
|
|
|
|
4
|
|
209
|
1
|
|
|
|
|
18
|
return \%col_hash; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head2 find_columns |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$request->find_columns( %options ) |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
where C<%options> hash accepts the following parameters: |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=over |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=item by_name |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
by_name accepts a scalar or arrayref of values and returns an arrayref of |
223
|
|
|
|
|
|
|
column definitions |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
my \@columns = $request->find_columns( by_name => ['col_name','col_name2'] ); |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Searchs the columns C and/or C parameter. |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=item search_field |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
my \@columns = $request->find_columns( by_name => 'something', search_field => 'name' ); |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
Set to either C or C to search those respective fields when |
234
|
|
|
|
|
|
|
doing a C seach. If no search_field is specified, C searches |
235
|
|
|
|
|
|
|
that match either field will be returned (i.e. defaults to search both fields) |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item by_idx |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
my \@columns = $request->find_columns( by_idx => $col_idx ) |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
This is just a passthrough to C<< $request->columns( $col_idx ); >> |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=back |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=cut |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub find_columns { |
248
|
3
|
|
|
3
|
1
|
942
|
my ($self, %options) = @_; |
249
|
3
|
50
|
|
|
|
9
|
return unless %options; |
250
|
|
|
|
|
|
|
|
251
|
3
|
100
|
|
|
|
9
|
if (defined($options{by_idx})) { |
252
|
1
|
|
|
|
|
7
|
return $self->columns($options{by_idx}); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
2
|
50
|
|
|
|
8
|
if (my $searches = $options{by_name}) { |
256
|
2
|
|
|
|
|
3
|
my $ret_cols; |
257
|
2
|
|
|
|
|
3
|
my $key = $options{search_field}; |
258
|
2
|
50
|
|
|
|
8
|
$searches = [ $searches ] if ref($searches) ne 'ARRAY'; |
259
|
2
|
|
|
|
|
7
|
my $col_ref = $self->_columns; |
260
|
|
|
|
|
|
|
|
261
|
2
|
|
|
|
|
26
|
foreach my $search_val ( @$searches ) { |
262
|
2
|
|
|
|
|
3
|
foreach my $col ( @$col_ref ) { |
263
|
2
|
50
|
|
|
|
6
|
if ( defined $key ) { |
264
|
0
|
0
|
|
|
|
0
|
if ( $col->{$key} eq $search_val ) { |
265
|
0
|
|
|
|
|
0
|
push(@$ret_cols, $col); |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
} else { |
268
|
2
|
50
|
33
|
|
|
8
|
if ( $col->{name} eq $search_val || $col->{data} eq $search_val ) { |
269
|
2
|
|
|
|
|
8
|
push(@$ret_cols, $col); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
} |
274
|
2
|
|
|
|
|
41
|
return $ret_cols; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=head2 order |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
$req->order(0)->{dir} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
Returns the order data at provided index. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=cut |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub order |
287
|
|
|
|
|
|
|
{ |
288
|
5
|
|
|
5
|
1
|
2151
|
my ($self,$idx) = @_; |
289
|
5
|
50
|
|
|
|
12
|
return unless defined($idx); |
290
|
5
|
|
|
|
|
14
|
return $self->_order->[$idx]; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 orders |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
$req->orders([0,1]); |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Returns an arrayref of the order data records at the provided indexes. Accepts an arrayref or scalar. |
298
|
|
|
|
|
|
|
C<< ->orders([0,1]) >> will get C and C data. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=cut |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub orders |
303
|
|
|
|
|
|
|
{ |
304
|
2
|
|
|
2
|
1
|
343
|
my ($self,$ar_idx) = @_; |
305
|
2
|
|
|
|
|
6
|
my $ord_ref = $self->_order; |
306
|
2
|
50
|
|
|
|
25
|
return $ord_ref unless defined($ar_idx); |
307
|
|
|
|
|
|
|
|
308
|
0
|
0
|
|
|
|
0
|
$ar_idx = [ $ar_idx ] unless ref($ar_idx) eq 'ARRAY'; |
309
|
|
|
|
|
|
|
|
310
|
0
|
|
|
|
|
0
|
my $ret_arr; |
311
|
0
|
|
|
|
|
0
|
foreach my $idx ( @$ar_idx ) { |
312
|
0
|
|
|
|
|
0
|
push(@$ret_arr, $ord_ref->[$idx]); |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
0
|
|
|
|
|
0
|
return $ret_arr; |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=head2 version |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
my $version = $request->version( \%client_params? ) |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Returns the version of DataTables we need to support based on the parameters sent. |
323
|
|
|
|
|
|
|
v1.9 version of DataTables sends different named parameters than v1.10. Returns a string |
324
|
|
|
|
|
|
|
of '1.9' if we think we have a 1.9 request, '1.10' if we think it is a 1.10 request or C |
325
|
|
|
|
|
|
|
if we dont' think it is a DataTables request at all. |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
This can be invoked as a class method as well as an instance method. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=cut |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub version |
332
|
|
|
|
|
|
|
{ |
333
|
13
|
|
|
13
|
1
|
484
|
my ($self,$client_params) = @_; |
334
|
|
|
|
|
|
|
|
335
|
13
|
100
|
66
|
|
|
50
|
if (!ref($self) && !defined($client_params)) { |
336
|
1
|
|
|
|
|
5
|
return; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
12
|
100
|
|
|
|
33
|
return $self->_version unless $client_params; |
340
|
10
|
|
|
|
|
13
|
my $ref = $client_params; |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# v1.10 parameters |
343
|
10
|
100
|
100
|
|
|
70
|
if (defined $ref->{draw} && defined $ref->{start} && defined $ref->{'length'}) { |
|
|
|
66
|
|
|
|
|
344
|
4
|
|
|
|
|
19
|
return '1.10'; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# v1.9 parameters |
348
|
6
|
50
|
66
|
|
|
41
|
if (defined $ref->{sEcho} && defined $ref->{iDisplayStart} && defined $ref->{iDisplayLength}) { |
|
|
|
66
|
|
|
|
|
349
|
3
|
|
|
|
|
11
|
return '1.9'; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
3
|
|
|
|
|
9
|
return; |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
=head1 PRIVATE METHODS |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head2 _process_v1_9_params |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
Processes v1.9 parameters, mapping them to 1.10 parameters |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
$self->_process_v1_9_params( \%client_params ) |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
where C<\%client_params> is a HashRef containing the v1.9 parameters that DataTables |
365
|
|
|
|
|
|
|
client library sends the server in server-side mode. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=cut |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# maps 1.9 to 1.10 variables |
370
|
|
|
|
|
|
|
# only thing not mapped is iColumns |
371
|
|
|
|
|
|
|
my $vmap = { |
372
|
|
|
|
|
|
|
top => { |
373
|
|
|
|
|
|
|
'iDisplayStart' => 'start', |
374
|
|
|
|
|
|
|
'iDisplayLength' => 'length', |
375
|
|
|
|
|
|
|
'sEcho' => 'draw', |
376
|
|
|
|
|
|
|
}, |
377
|
|
|
|
|
|
|
col_and_order => { |
378
|
|
|
|
|
|
|
'bSearchable' => ['columns', 'searchable', undef], |
379
|
|
|
|
|
|
|
'sSearch' => ['columns', 'search', 'value'], |
380
|
|
|
|
|
|
|
'bRegex' => ['columns', 'search', 'regex'], |
381
|
|
|
|
|
|
|
'bSortable' => ['columns', 'orderable', undef], |
382
|
|
|
|
|
|
|
'mDataProp' => ['columns', 'data', undef], |
383
|
|
|
|
|
|
|
'iSortCol' => ['order', 'column', undef], |
384
|
|
|
|
|
|
|
'sSortDir' => ['order', 'dir', undef] |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
}; |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub _process_v1_9_params { |
389
|
2
|
|
|
2
|
|
4
|
my ($self, $client_params) = @_; |
390
|
2
|
|
|
|
|
5
|
my $columns; |
391
|
|
|
|
|
|
|
my $order; |
392
|
0
|
|
|
|
|
0
|
my $search; |
393
|
|
|
|
|
|
|
|
394
|
2
|
|
|
|
|
13
|
while ( my ($name,$val) = each %$client_params ) { |
395
|
|
|
|
|
|
|
# handle top level parameters |
396
|
28
|
100
|
|
|
|
120
|
if ( grep { $_ eq $name && $val =~ m/^[0-9]+$/ } keys %{$vmap->{top}} ) { |
|
84
|
100
|
|
|
|
347
|
|
|
28
|
100
|
|
|
|
68
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
397
|
6
|
|
|
|
|
15
|
my $acc = $vmap->{top}->{$name}; |
398
|
6
|
|
|
|
|
42
|
$self->$acc( $val ); |
399
|
|
|
|
|
|
|
} elsif ($name eq 'sSearch') { |
400
|
2
|
|
|
|
|
19
|
$search->{value} = $val; |
401
|
|
|
|
|
|
|
} elsif ($name eq 'bRegex') { |
402
|
2
|
50
|
|
|
|
13
|
$search->{regex} = $val eq 'true' ? 1 : 0; |
403
|
|
|
|
|
|
|
} elsif ($name =~ m/^(?bSearchable|sSearch|bRegex|bSortable|iSortCol|sSortDir|mDataProp)_(?\d+)$/) { |
404
|
4
|
|
|
4
|
|
37725
|
my $map = $vmap->{col_and_order}->{$+{param}}; |
|
4
|
|
|
|
|
2298
|
|
|
4
|
|
|
|
|
3813
|
|
|
14
|
|
|
|
|
94
|
|
405
|
14
|
|
|
|
|
69
|
my ($param,$idx,$sub_param1,$sub_param2,$new_val) = |
406
|
|
|
|
|
|
|
$self->_validate_and_convert( $map->[0], $+{idx}, $map->[1], $map->[2], $val); |
407
|
|
|
|
|
|
|
|
408
|
14
|
100
|
|
|
|
51
|
if ($map->[0] eq 'columns') { |
|
|
50
|
|
|
|
|
|
409
|
10
|
100
|
|
|
|
40
|
if (defined($sub_param2)) { |
410
|
4
|
|
|
|
|
25
|
$columns->{$idx}{$sub_param1}{$sub_param2} = $new_val; |
411
|
|
|
|
|
|
|
} else { |
412
|
6
|
|
|
|
|
15
|
$columns->{$idx}{$sub_param1} = $new_val; |
413
|
|
|
|
|
|
|
# copy name => data for v1.9 so that find_columns works as expected |
414
|
|
|
|
|
|
|
# not really sure how to do this, Data::Alias? alias it eventually |
415
|
|
|
|
|
|
|
# right now just copy |
416
|
6
|
100
|
|
|
|
37
|
if ($sub_param1 eq 'data') { |
417
|
2
|
|
|
|
|
12
|
$columns->{$idx}{'name'} = $new_val; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
} elsif ($map->[0] eq 'order') { |
421
|
4
|
|
|
|
|
25
|
$order->{$idx}{$sub_param1} = $new_val; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
2
|
|
|
|
|
5
|
my @col_arr; |
427
|
2
|
|
|
|
|
12
|
push(@col_arr, $columns->{$_}) for ( sort keys %$columns ); |
428
|
|
|
|
|
|
|
|
429
|
2
|
|
|
|
|
4
|
my @order_arr; |
430
|
2
|
|
|
|
|
9
|
push(@order_arr, $order->{$_}) for ( sort keys %$order ); |
431
|
|
|
|
|
|
|
|
432
|
2
|
|
|
|
|
9
|
$self->_columns( \@col_arr ); |
433
|
2
|
|
|
|
|
25
|
$self->_order( \@order_arr ); |
434
|
2
|
|
|
|
|
20
|
$self->search( $search ); |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=head2 _process_v1_10_params |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
$self->_process_v1_10_params( \%client_params ); |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
where C<\%client_params> is a HashRef containing the v1.10 parameters that DataTables |
442
|
|
|
|
|
|
|
client library sends the server in server-side mode. |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=cut |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub _process_v1_10_params { |
447
|
3
|
|
|
3
|
|
8
|
my ($self, $client_params) = @_; |
448
|
|
|
|
|
|
|
|
449
|
3
|
|
|
|
|
6
|
my $columns; |
450
|
|
|
|
|
|
|
my $order; |
451
|
0
|
|
|
|
|
0
|
my $search; |
452
|
3
|
|
|
|
|
19
|
while ( my ($name,$val) = each %$client_params ) { |
453
|
47
|
100
|
|
|
|
69
|
$self->$name( $val ) if ( grep { $_ eq $name && $val =~ m/^[0-9]+$/ } qw(draw start length) ); |
|
141
|
100
|
|
|
|
518
|
|
454
|
|
|
|
|
|
|
|
455
|
47
|
100
|
|
|
|
409
|
if ($name =~ m/^(?columns|order)\[(?[0-9]+)\]\[(?[^]]+)\](\[(?[^]]+)\])?$/) { |
|
|
100
|
|
|
|
|
|
456
|
32
|
|
|
|
|
305
|
my ($param,$idx,$sub_param1,$sub_param2,$new_val) = |
457
|
|
|
|
|
|
|
$self->_validate_and_convert($+{param}, $+{idx}+0, $+{sub_param1}, $+{sub_param2}, $val); |
458
|
|
|
|
|
|
|
|
459
|
32
|
100
|
|
|
|
151
|
if ($param eq 'columns') { |
|
|
50
|
|
|
|
|
|
460
|
24
|
100
|
|
|
|
43
|
if (defined($sub_param2)) { |
461
|
8
|
|
|
|
|
45
|
$columns->{$idx}{$sub_param1}{$sub_param2} = $new_val; |
462
|
|
|
|
|
|
|
} else { |
463
|
16
|
|
|
|
|
91
|
$columns->{$idx}{$sub_param1} = $new_val; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
} elsif ($param eq 'order') { |
466
|
8
|
|
|
|
|
16020
|
$order->{$idx}{$sub_param1} = $new_val; |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
} elsif ($name =~ m/^search\[(?regex|value)\]$/) { |
469
|
6
|
|
|
|
|
42
|
my $sp = $+{search_param}; |
470
|
6
|
100
|
|
|
|
23
|
if ($sp eq 'regex') { |
471
|
3
|
100
|
|
|
|
23
|
$search->{$sp} = $val eq 'true' ? 1 : 0; |
472
|
|
|
|
|
|
|
} else { |
473
|
3
|
|
|
|
|
33
|
$search->{$sp} = $val; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
3
|
|
|
|
|
43
|
my @col_arr; |
479
|
3
|
|
|
|
|
31
|
push(@col_arr, $columns->{$_}) for ( sort keys %$columns ); |
480
|
|
|
|
|
|
|
|
481
|
3
|
|
|
|
|
7
|
my @order_arr; |
482
|
3
|
|
|
|
|
16
|
push(@order_arr, $order->{$_}) for ( sort keys %$order ); |
483
|
|
|
|
|
|
|
|
484
|
3
|
|
|
|
|
17
|
$self->_columns( \@col_arr ); |
485
|
3
|
|
|
|
|
51
|
$self->_order( \@order_arr ); |
486
|
3
|
|
|
|
|
36
|
$self->search( $search ); |
487
|
3
|
|
|
|
|
34
|
return $self; |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head2 _validate_and_convert |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Validates parameters are set properly and does boolean conversion |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=cut |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
#XXX: make this not a mess |
497
|
|
|
|
|
|
|
sub _validate_and_convert |
498
|
|
|
|
|
|
|
{ |
499
|
46
|
|
|
46
|
|
248
|
my ($self,$param,$idx,$sub1,$sub2,$val) = @_; |
500
|
46
|
100
|
|
|
|
173
|
if ($param eq 'columns') { |
|
|
50
|
|
|
|
|
|
501
|
34
|
100
|
100
|
|
|
212
|
if ($sub1 eq 'orderable' || $sub1 eq 'searchable') { |
|
|
100
|
100
|
|
|
|
|
502
|
12
|
100
|
|
|
|
35
|
$val = lc $val eq 'true' ? 1 : 0; |
503
|
|
|
|
|
|
|
} elsif ( $sub1 eq 'search' && $sub2 eq 'regex' ) { |
504
|
6
|
100
|
|
|
|
22
|
$val = lc $val eq 'true' ? 1 : 0; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
} elsif ($param eq 'order') { |
507
|
12
|
50
|
100
|
|
|
67
|
if ($sub1 eq 'dir' && lc $val ne 'asc' && lc $val ne 'desc') { |
|
|
|
66
|
|
|
|
|
508
|
|
|
|
|
|
|
#warn 'Unknown order[dir] value provided. Must be asc or desc, defaulting to asc'; |
509
|
0
|
|
|
|
|
0
|
$val = 'asc'; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
} |
512
|
46
|
|
|
|
|
168
|
return ($param,$idx,$sub1,$sub2,$val); |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head1 AUTHOR |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
Mike Wisener Exmikew_cpan_orgE |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Copyright E 2014 by Mike Wisener |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
524
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=cut |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
1; |