Revision 460cd14e
Von Moritz Bunkus vor fast 12 Jahren hinzugefügt
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
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