1dae8ccbdac531fddfbc83e01eb020c158c5f200
[kivitendo-erp.git] / SL / DB / Helper / Presenter.pm
1 package SL::DB::Helper::Presenter;
2
3 use strict;
4
5 sub new {
6   # lightweight: 0: class, 1: object
7   bless [ $_[1], $_[2] ], $_[0];
8 }
9
10 sub AUTOLOAD {
11   our $AUTOLOAD;
12
13   my ($self, @args) = @_;
14
15   my $method = $AUTOLOAD;
16   $method    =~ s/.*:://;
17
18   return if $method eq 'DESTROY';
19
20   eval "require $self->[0]";
21
22   splice @args, -1, 1, %{ $args[-1] } if @args && (ref($args[-1]) eq 'HASH');
23
24   if (my $sub = $self->[0]->can($method)) {
25     return $sub->($self->[1], @args);
26   }
27 }
28
29 sub can {
30   my ($self, $method) = @_;
31   eval "require $self->[0]";
32   $self->[0]->can($method);
33 }
34
35 1;
36
37 __END__
38
39 =encoding utf-8
40
41 =head1 NAME
42
43 SL::DB::Helper::Presenter - proxy class to allow models to access presenters
44
45 =head1 SYNOPSIS
46
47   # assuming SL::Presenter::Part exists
48   # and contains a sub link_to($class, $object) {}
49   SL::DB::Part->new(%args)->presenter->link_to
50
51 =head1 DESCRIPTION
52
53 When coding controllers one often encounters objects that are not crucial to
54 the current task, but must be presented in some form to the user. Instead of
55 recreating that all the time the C<SL::Presenter> namepace was introduced to
56 hold such code.
57
58 Unfortunately the Presenter code is designed to be stateless and thus acts _on_
59 objects, but can't be instanced or wrapped. The early band-aid to that was to
60 export all sub-presenter calls into the main presenter namespace. Fixing it
61 would have meant accessing presenter functions like this:
62
63   SL::Presenter::Object->method($object, %additional_args)
64
65 which is extremely inconvenient.
66
67 This glue code allows C<SL::DB::Object> instances to access routines in their
68 presenter without additional boilerplate. C<SL::DB::Object> contains a
69 C<presenter> call for all objects, which will return an instance of this proxy
70 class. All calls on this will then be forwarded to the appropriate presenter.
71
72 =head1 INTERNAL STRUCTURE
73
74 The created proxy objects are lightweight blessed arrayrefs instead of the
75 usual blessed hashrefs. They only store two elements:
76
77 =over 4
78
79 =item * The presenter class
80
81 =item * The invocing object
82
83 =back
84
85 Further delegation is done with C<AUTOLOAD>.
86
87 =head1 BUGS
88
89 None yet :)
90
91 =head1 AUTHOR
92
93 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
94
95 =cut