a1183d75fcf1094f3e31fb7e2024ebc818280a21
[kivitendo-erp.git] / SL / DB / Helper / LinkedRecords.pm
1 package SL::DB::Helpers::LinkedRecords;
2
3 require Exporter;
4 our @ISA    = qw(Exporter);
5 our @EXPORT = qw(linked_records link_to_record);
6
7 use Carp;
8
9 use SL::DB::Helpers::Mappings;
10 use SL::DB::RecordLink;
11
12 sub linked_records {
13   my $self     = shift;
14   my %params   = @_;
15
16   my $wanted   = $params{direction} || croak("Missing parameter `direction'");
17   my $myself   = $wanted eq 'from' ? 'to' : $wanted eq 'to' ? 'from' : croak("Invalid parameter `direction'");
18
19   my $my_table = SL::DB::Helpers::Mappings::get_table_for_package(ref($self));
20
21   my @query    = ( "${myself}_table" => $my_table,
22                    "${myself}_id"    => $self->id );
23
24   if ($params{$wanted}) {
25     my $wanted_table = SL::DB::Helpers::Mappings::get_table_for_package($params{$wanted}) || croak("Invalid parameter `${wanted}'");
26     push @query, ("${wanted}_table" => $wanted_table);
27   }
28
29   my $links            = SL::DB::Manager::RecordLink->get_all(query => [ and => \@query ]);
30
31   my $sub_wanted_table = "${wanted}_table";
32   my $sub_wanted_id    = "${wanted}_id";
33
34   my $records          = [];
35   @query               = ref($params{query}) eq 'ARRAY' ? @{ $params{query} } : ();
36
37   foreach my $link (@{ $links }) {
38     my $class = SL::DB::Helpers::Mappings::get_manager_package_for_table($link->$sub_wanted_table);
39     push @{ $records }, @{ $class->get_all(query => [ id => $link->$sub_wanted_id, @query ]) };
40   }
41
42   return $records;
43 }
44
45 sub link_to_record {
46   my $self   = shift;
47   my $other  = shift;
48
49   croak "self has no id"  unless $self->id;
50   croak "other has no id" unless $other->id;
51
52   my %params = ( from_table => SL::DB::Helpers::Mappings::get_table_for_package(ref($self)),
53                  from_id    => $self->id,
54                  to_table   => SL::DB::Helpers::Mappings::get_table_for_package(ref($other)),
55                  to_id      => $other->id,
56                );
57
58   my $link = SL::DB::Manager::RecordLink->find_by(and => [ %params ]);
59   return $link ? $link : SL::DB::RecordLink->new(%params)->save;
60 }
61
62 1;
63
64 __END__
65
66 =encoding utf8
67
68 =head1 NAME
69
70 SL::DB::Helpers::LinkedRecords - Mixin for retrieving linked records via the table C<record_links>
71
72 =head1 FUNCTIONS
73
74 =over 4
75
76 =item C<linked_records %params>
77
78 Retrieves records linked from or to C<$self> via the table
79 C<record_links>. The mandatory parameter C<direction> (either C<from>
80 or C<to>) determines whether the function retrieves records that link
81 to C<$self> (for C<direction> = C<to>) or that are linked from
82 C<$self> (for C<direction> = C<from>).
83
84 The optional parameter C<from> or C<to> (same as C<direction>)
85 contains the package name of a Rose model for table limitation. If you
86 only need invoices created from an order C<$order> then the call could
87 look like this:
88
89   my $invoices = $order->linked_records(direction => 'to',
90                                         to        => 'SL::DB::Invoice');
91
92 The optional parameter C<query> can be used to limit the records
93 returned. The following call limits the earlier example to invoices
94 created today:
95
96   my $invoices = $order->linked_records(direction => 'to',
97                                         to        => 'SL::DB::Invoice',
98                                         query     => [ transdate => DateTime->today_local ]);
99
100 Returns an array reference.
101
102 =item C<link_to_record $record>
103
104 Will create an entry in the table C<record_links> with the C<from>
105 side being C<$self> and the C<to> side being C<$record>. Will only
106 insert a new entry if such a link does not already exist.
107
108 Returns either the existing link or the newly created one as an
109 instance of C<SL::DB::RecordLink>.
110
111 =back
112
113 =head1 BUGS
114
115 Nothing here yet.
116
117 =head1 AUTHOR
118
119 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
120
121 =cut