Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 460cd14e

Von Moritz Bunkus vor fast 12 Jahren hinzugefügt

  • ID 460cd14ecfb30a599884bb7dffbcdcdca9e7c432
  • Vorgänger d183ece1
  • Nachfolger 61bd6288

LinkedRecords-Helfer: Parameter 'via' bei 'linked_records' für beliebige Pfade von -> zu

z.B. um zu einem Angebot alle Rechnungen zu erhalten, egal, ob
zwischendurch Aufträge und Lieferscheine stehen

Unterschiede anzeigen:

SL/DB/Helper/LinkedRecords.pm
45 45
    return [ values %record_map ];
46 46
  }
47 47

  
48
  my $myself   = $wanted eq 'from' ? 'to' : $wanted eq 'to' ? 'from' : croak("Invalid parameter `direction'");
48
  if ($params{via}) {
49
    croak("Cannot use 'via' without '${wanted}_table'")             if !$params{$wanted};
50
    croak("Cannot use 'via' with '${wanted}_table' being an array") if ref $params{$wanted};
51
  }
49 52

  
50
  my $my_table = SL::DB::Helper::Mappings::get_table_for_package(ref($self));
53
  my $myself           = $wanted eq 'from' ? 'to' : $wanted eq 'to' ? 'from' : croak("Invalid parameter `direction'");
54
  my $my_table         = SL::DB::Helper::Mappings::get_table_for_package(ref($self));
51 55

  
52
  my @query    = ( "${myself}_table" => $my_table,
53
                   "${myself}_id"    => $self->id );
56
  my $sub_wanted_table = "${wanted}_table";
57
  my $sub_wanted_id    = "${wanted}_id";
54 58

  
59
  my ($wanted_classes, $wanted_tables);
55 60
  if ($params{$wanted}) {
56
    my $wanted_classes = ref($params{$wanted}) eq 'ARRAY' ? $params{$wanted} : [ $params{$wanted} ];
57
    my $wanted_tables  = [ map { SL::DB::Helper::Mappings::get_table_for_package($_) || croak("Invalid parameter `${wanted}'") } @{ $wanted_classes } ];
58
    push @query, ("${wanted}_table" => $wanted_tables);
61
    $wanted_classes = ref($params{$wanted}) eq 'ARRAY' ? $params{$wanted} : [ $params{$wanted} ];
62
    $wanted_tables  = [ map { SL::DB::Helper::Mappings::get_table_for_package($_) || croak("Invalid parameter `${wanted}'") } @{ $wanted_classes } ];
59 63
  }
60 64

  
61
  my $links            = SL::DB::Manager::RecordLink->get_all(query => [ and => \@query ]);
65
  my @get_objects_query = ref($params{query}) eq 'ARRAY' ? @{ $params{query} } : ();
66
  my $get_objects       = sub {
67
    my $manager_class = SL::DB::Helper::Mappings::get_manager_package_for_table($_[0]->$sub_wanted_table);
68
    my $object_class  = SL::DB::Helper::Mappings::get_package_for_table($_[0]->$sub_wanted_table);
69
    eval "require " . $object_class . "; 1;";
70
    return @{ $manager_class->get_all(query => [ id => $_[0]->$sub_wanted_id, @get_objects_query ]) };
71
  };
62 72

  
63
  my $sub_wanted_table = "${wanted}_table";
64
  my $sub_wanted_id    = "${wanted}_id";
73
  # If no 'via' is given then use a simple(r) method for querying the wanted objects.
74
  if (!$params{via}) {
75
    my @query = ( "${myself}_table" => $my_table,
76
                  "${myself}_id"    => $self->id );
77
    push @query, ( "${wanted}_table" => $wanted_tables ) if $wanted_tables;
65 78

  
66
  my $records          = [];
67
  @query               = ref($params{query}) eq 'ARRAY' ? @{ $params{query} } : ();
79
    return [ map { $get_objects->($_) } @{ SL::DB::Manager::RecordLink->get_all(query => [ and => \@query ]) } ];
80
  }
68 81

  
69
  foreach my $link (@{ $links }) {
70
    my $manager_class = SL::DB::Helper::Mappings::get_manager_package_for_table($link->$sub_wanted_table);
71
    my $object_class  = SL::DB::Helper::Mappings::get_package_for_table($link->$sub_wanted_table);
72
    eval "require " . $object_class . "; 1;";
73
    push @{ $records }, @{ $manager_class->get_all(query => [ id => $link->$sub_wanted_id, @query ]) };
82
  # More complex handling for the 'via' case.
83
  my @sources = ( $self );
84
  my @targets = map { SL::DB::Helper::Mappings::get_table_for_package($_) } @{ ref($params{via}) ? $params{via} : [ $params{via} ] };
85
  push @targets, @{ $wanted_tables } if $wanted_tables;
86

  
87
  my %seen = map { ($_->meta->table . $_->id => 1) } @sources;
88

  
89
  while (@targets) {
90
    my @new_sources = @sources;
91
    foreach my $src (@sources) {
92
      my @query = ( "${myself}_table" => $src->meta->table,
93
                    "${myself}_id"    => $src->id,
94
                    "${wanted}_table" => \@targets );
95
      push @new_sources,
96
           map  { $get_objects->($_) }
97
           grep { !$seen{$_->$sub_wanted_table . $_->$sub_wanted_id} }
98
           @{ SL::DB::Manager::RecordLink->get_all(query => [ and => \@query ]) };
99
    }
100

  
101
    @sources = @new_sources;
102
    %seen    = map { ($_->meta->table . $_->id => 1) } @sources;
103
    shift @targets;
74 104
  }
75 105

  
76
  return $records;
106
  my %wanted_tables_map = map  { ($_ => 1) } @{ $wanted_tables };
107
  return [ grep { $wanted_tables_map{$_->meta->table} } @sources ];
77 108
}
78 109

  
79 110
sub link_to_record {
......
215 246
single scalar or multiple model names in an array reference in which
216 247
case all links matching any of the model names will be returned.
217 248

  
218
If you only need invoices created from an order C<$order> then the
219
call could look like this:
249
The optional parameter C<via> can be used to retrieve all documents
250
that may have intermediate documents inbetween. It is an array
251
reference of Rose package names for the models that may be
252
intermediate link targets. One example is retrieving all invoices for
253
a given quotation no matter whether or not orders and delivery orders
254
have been created. If C<via> is given then C<from> or C<to> (depending
255
on C<direction>) must be given as well, and it must then not be an
256
array reference.
257

  
258
Examples:
259

  
260
If you only need invoices created directly from an order C<$order> (no
261
delivery orders inbetween) then the call could look like this:
220 262

  
221 263
  my $invoices = $order->linked_records(direction => 'to',
222 264
                                        to        => 'Invoice');
223 265

  
266
Retrieving all invoices from a quotation no matter whether or not
267
orders or delivery orders where created:
268

  
269
  my $invoices = $quotation->linked_records(direction => 'to',
270
                                            to        => 'Invoice',
271
                                            via       => [ 'Order', 'DeliveryOrder' ]);
272

  
224 273
The optional parameter C<query> can be used to limit the records
225 274
returned. The following call limits the earlier example to invoices
226 275
created today:

Auch abrufbar als: Unified diff