Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 1264cff6

Von Sven Schöling vor mehr als 11 Jahren hinzugefügt

  • ID 1264cff68a2e27855c34fc2e00e1f6724ab004f4
  • Vorgänger 9fac28d8
  • Nachfolger a45d8cbe

ParseFilter auf Objektdispatch erweitert

Unterschiede anzeigen:

SL/Controller/Helper/ParseFilter.pm
95 95
  my @result;
96 96
  for (my $i = 0; $i < scalar @$flattened; $i += 2) {
97 97
    my ($key, $value) = ($flattened->[$i], $flattened->[$i+1]);
98

  
98 99
    ($key, $value) = _apply_all($key, $value, qr/\b:(\w+)/,  { %filters, %{ $params{filters} || {} } });
99 100
    ($key, $value) = _apply_all($key, $value, qr/\b::(\w+)/, { %methods, %{ $params{methods} || {} } });
101
    ($key, $value) = _dispatch_custom_filters($params{class}, $key, $value) if $params{class};
102

  
100 103
    push @result, $key, $value;
101 104
  }
102 105
  return \@result;
103 106
}
104 107

  
108
sub _dispatch_custom_filters {
109
  my ($class, $key, $value) = @_;
110

  
111
  # the key should by now have no filters left
112
  # if it has, catch it here:
113
  die 'unrecognized filters' if $key =~ /:/;
114

  
115
  my @tokens     = split /\./, $key;
116
  my $last_token = pop @tokens;
117
  my $curr_class = $class->object_class;
118

  
119
  for my $token (@tokens) {
120
    eval {
121
      $curr_class = $curr_class->meta->relationship($token)->class;
122
      1;
123
    } or do {
124
      require Carp;
125
      Carp::croak("Could not resolve the relationship '$token' in '$key' while building the filter request");
126
    }
127
  }
128

  
129
  my $manager = $curr_class->meta->convention_manager->auto_manager_class_name;
130

  
131
  if ($manager->can('filter')) {
132
    ($key, $value) = $manager->filter($last_token, $value, join '.', @tokens, '');
133
  }
134

  
135
  return ($key, $value);
136
}
137

  
105 138
sub _collapse_indirect_filters {
106 139
  my ($flattened) = @_;
107 140

  
......
227 260
match method suffixes, which are appended with 2 colons. See below for a full
228 261
list of modifiers.
229 262

  
230
The reason for the method being last is that it is possible to specify the
231
method in another input. Suppose you want a date input and a separate
232
before/after/equal select, you can use the following:
233

  
234
  [% L.date_tag('filter.appointed_date:date', ... ) %]
235

  
236
and later
237

  
238
  [% L.select_tag('filter.appointed_date::', ... ) %]
239

  
240
The special empty method will be used to set the method for the previous
241
method-less input.
242

  
243 263
=back
244 264

  
245 265
=head1 LAUNDERING
......
273 293
    'closed            => '1',
274 294
  }
275 295

  
296
=head1 INDIRECT FILTER METHODS
297

  
298
The reason for the method being last is that it is possible to specify the
299
method in another input. Suppose you want a date input and a separate
300
before/after/equal select, you can use the following:
301

  
302
  [% L.date_tag('filter.appointed_date:date', ... ) %]
303

  
304
and later
305

  
306
  [% L.select_tag('filter.appointed_date:date::', ... ) %]
307

  
308
The special empty method will be used to set the method for the previous
309
method-less input.
310

  
311
=head1 CUSTOM FILTERS FROM OBJECTS
312

  
313
If the L<parse_filter> call contains a parameter C<class>, custom filters will
314
be honored. Suppose you have added a custom filter 'all' for parts which
315
expands to search both description and partnumber, the following
316

  
317
  $filter = {
318
    'part.all:substr::ilike' => 'A1',
319
  }
320

  
321
will expand to:
322

  
323
  query => [
324
    or => [
325
      part.description => { ilike => '%A1%' },
326
      part.partnumber  => { ilike => '%A1%' },
327
    ]
328
  ]
329

  
330
For more abuot custom filters, see L<SL::DB::Helper::Filtered>.
331

  
276 332
=head1 FILTERS (leading with :)
277 333

  
278 334
The following filters are built in, and can be used.
......
334 390
  L.input_tag('customer.name:substr::ilike', ...)
335 391
  L.input_tag('invoice.customer.name:substr::ilike', ...)
336 392

  
337
This will sarch for orders whoe invoice has the _same_ customer, which matches
393
This will sarch for orders whose invoice has the _same_ customer, which matches
338 394
both inputs. This is because tables are aliased by their name and not by their
339 395
position in with_objects.
340 396

  
t/controllers/helpers/parse_filter.t
1 1
use lib 't';
2 2

  
3
use Test::More tests => 18;
3
use Test::More tests => 23;
4 4
use Test::Deep;
5 5
use Data::Dumper;
6 6

  
7 7
use_ok 'Support::TestSetup';
8 8
use_ok 'SL::Controller::Helper::ParseFilter';
9 9

  
10
use SL::DB::OrderItem;
11

  
10 12
undef *::any; # Test::Deep exports any (for junctions) and MoreCommon exports any (like in List::Moreutils)
11 13

  
12 14
Support::TestSetup::login();
......
190 192
  with_objects => bag('order.customer', 'order'),
191 193
}, 'sub objects have to retain their prefix';
192 194

  
195
### class filter dispatch
196
#
197
test {
198
  name => 'Test',
199
  whut => 'moof',
200
}, {
201
  query => bag(
202
    name => 'Test',
203
    whut => 'moof'
204
  ),
205
}, 'object test simple', class => 'SL::DB::Manager::Part';
206

  
207
test {
208
  'type' => 'assembly',
209
}, {
210
  query => [
211
    'assembly' => 1
212
  ],
213
}, 'object test without prefix', class => 'SL::DB::Manager::Part';
214

  
215
test {
216
  'part.type' => 'assembly',
217
}, {
218
  query => [
219
    'part.assembly' => 1
220
  ],
221
}, 'object test with prefix', class => 'SL::DB::Manager::OrderItem';
222

  
223
test {
224
  'type' => [ 'part', 'assembly' ],
225
}, {
226
  query => [
227
    or => [
228
     and => [ or => [ assembly => 0, assembly => undef ],
229
              "!inventory_accno_id" => 0,
230
              "!inventory_accno_id" => undef,
231
     ],
232
     assembly => 1,
233
    ]
234
  ],
235
}, 'object test without prefix but complex value', class => 'SL::DB::Manager::Part';
236

  
237
test {
238
  'part.type' => [ 'part', 'assembly' ],
239
}, {
240
  query => [
241
    or => [
242
     and => [ or => [ 'part.assembly' => 0, 'part.assembly' => undef ],
243
              "!part.inventory_accno_id" => 0,
244
              "!part.inventory_accno_id" => undef,
245
     ],
246
     'part.assembly' => 1,
247
    ]
248
  ],
249
}, 'object test with prefix but complex value', class => 'SL::DB::Manager::OrderItem';

Auch abrufbar als: Unified diff