-package SL::DB::Helpers::LinkedRecords;
+package SL::DB::Helper::LinkedRecords;
use strict;
require Exporter;
our @ISA = qw(Exporter);
-our @EXPORT = qw(linked_records link_to_record linked_records_sorted);
+our @EXPORT = qw(linked_records link_to_record);
use Carp;
use Sort::Naturally;
-use SL::DB::Helpers::Mappings;
+use SL::DB::Helper::Mappings;
use SL::DB::RecordLink;
sub linked_records {
+ my ($self, %params) = @_;
+
+ my %sort_spec = ( by => delete($params{sort_by}),
+ dir => delete($params{sort_dir}) );
+ my $filter = delete $params{filter};
+
+ my $records = linked_records_implementation($self, %params);
+ $records = filter_linked_records($self, $filter, @{ $records }) if $filter;
+ $records = sort_linked_records($self, $sort_spec{by}, $sort_spec{dir}, @{ $records }) if $sort_spec{by};
+
+ return $records;
+}
+
+sub linked_records_implementation {
my $self = shift;
my %params = @_;
my %from_to = ( from => delete($params{from}) || $both,
to => delete($params{to}) || $both);
- my @records = (@{ $self->linked_records(%params, direction => 'from', from => $from_to{from}) },
- @{ $self->linked_records(%params, direction => 'to', to => $from_to{to} ) });
+ my @records = (@{ linked_records_implementation($self, %params, direction => 'from', from => $from_to{from}) },
+ @{ linked_records_implementation($self, %params, direction => 'to', to => $from_to{to} ) });
my %record_map = map { ( ref($_) . $_->id => $_ ) } @records;
my $myself = $wanted eq 'from' ? 'to' : $wanted eq 'to' ? 'from' : croak("Invalid parameter `direction'");
- my $my_table = SL::DB::Helpers::Mappings::get_table_for_package(ref($self));
+ my $my_table = SL::DB::Helper::Mappings::get_table_for_package(ref($self));
my @query = ( "${myself}_table" => $my_table,
"${myself}_id" => $self->id );
if ($params{$wanted}) {
my $wanted_classes = ref($params{$wanted}) eq 'ARRAY' ? $params{$wanted} : [ $params{$wanted} ];
- my $wanted_tables = [ map { SL::DB::Helpers::Mappings::get_table_for_package($_) || croak("Invalid parameter `${wanted}'") } @{ $wanted_classes } ];
+ my $wanted_tables = [ map { SL::DB::Helper::Mappings::get_table_for_package($_) || croak("Invalid parameter `${wanted}'") } @{ $wanted_classes } ];
push @query, ("${wanted}_table" => $wanted_tables);
}
@query = ref($params{query}) eq 'ARRAY' ? @{ $params{query} } : ();
foreach my $link (@{ $links }) {
- my $manager_class = SL::DB::Helpers::Mappings::get_manager_package_for_table($link->$sub_wanted_table);
- my $object_class = SL::DB::Helpers::Mappings::get_package_for_table($link->$sub_wanted_table);
+ my $manager_class = SL::DB::Helper::Mappings::get_manager_package_for_table($link->$sub_wanted_table);
+ my $object_class = SL::DB::Helper::Mappings::get_package_for_table($link->$sub_wanted_table);
eval "require " . $object_class . "; 1;";
push @{ $records }, @{ $manager_class->get_all(query => [ id => $link->$sub_wanted_id, @query ]) };
}
my @links;
foreach my $direction (@directions) {
- my %params = ( $direction->[0] . "_table" => SL::DB::Helper::Mappings::get_table_for_package(ref($self)),
- $direction->[0] . "_id" => $self->id,
- $direction->[1] . "_table" => SL::DB::Helper::Mappings::get_table_for_package(ref($other)),
- $direction->[1] . "_id" => $other->id,
- );
-
- my $link = SL::DB::Manager::RecordLink->find_by(and => [ %params ]);
- push @links, $link ? $link : SL::DB::RecordLink->new(%params)->save unless $link;
+ my %data = ( $direction->[0] . "_table" => SL::DB::Helper::Mappings::get_table_for_package(ref($self)),
+ $direction->[0] . "_id" => $self->id,
+ $direction->[1] . "_table" => SL::DB::Helper::Mappings::get_table_for_package(ref($other)),
+ $direction->[1] . "_id" => $other->id,
+ );
+
+ my $link = SL::DB::Manager::RecordLink->find_by(and => [ %data ]);
+ push @links, $link ? $link : SL::DB::RecordLink->new(%data)->save unless $link;
}
return wantarray ? @links : $links[0];
}
-sub linked_records_sorted {
- my ($self, $sort_by, $sort_dir, %params) = @_;
-
- return sort_linked_records($self, $sort_by, $sort_dir, $self->linked_records(%params));
-}
-
sub sort_linked_records {
my ($self_or_class, $sort_by, $sort_dir, @records) = @_;
return [ sort($comparator @records) ];
}
+sub filter_linked_records {
+ my ($self_or_class, $filter, @records) = @_;
+
+ if ($filter eq 'accessible') {
+ my $employee = SL::DB::Manager::Employee->current;
+ @records = grep { !$_->can('may_be_accessed') || $_->may_be_accessed($employee) } @records;
+ } else {
+ croak "Unsupported filter parameter '${filter}'";
+ }
+
+ return \@records;
+}
+
1;
__END__
=head1 NAME
-SL::DB::Helpers::LinkedRecords - Mixin for retrieving linked records via the table C<record_links>
+SL::DB::Helper::LinkedRecords - Mixin for retrieving linked records via the table C<record_links>
=head1 FUNCTIONS
to => 'SL::DB::Invoice',
query => [ transdate => DateTime->today_local ]);
+The optional parameters C<$params{sort_by}> and C<$params{sort_dir}>
+can be used in order to sort the result. If C<$params{sort_by}> is
+trueish then the result is sorted by calling L</sort_linked_records>.
+
+The optional parameter C<$params{filter}> controls whether or not the
+result is filtered. Supported values are:
+
+=over 2
+
+=item C<accessible>
+
+Removes all objects for which the function C<may_be_accessed> from the
+mixin L<SL::DB::Helper::MayBeAccessed> exists and returns falsish for
+the current employee.
+
+=back
+
Returns an array reference.
=item C<link_to_record $record, %params>
This function is not exported.
-=item C<linked_records_sorted $sort_by, $sort_dir, %params>
-
-Returns the result of L</linked_records> sorted by
-L</sort_linked_records>. C<%params> is passed to
-L</linked_records>. C<$sort_by> and C<$sort_dir> are passed to
-L</sort_linked_records>.
-
=back
=head1 EXPORTS
-This mixin exports the functions L</linked_records>,
-L</link_to_record> and L</linked_records_sorted>.
+This mixin exports the functions L</linked_records> and
+L</link_to_record>.
=head1 BUGS