RDBO Support.
[kivitendo-erp.git] / SL / DB / Object.pm
1 package SL::DB::Object;
2
3 use strict;
4
5 use Readonly;
6 use Rose::DB::Object;
7 use List::MoreUtils qw(any);
8
9 use SL::DB;
10 use SL::DB::Helpers::AttrNumber;
11 use SL::DB::Helpers::AttrDate;
12 use SL::DB::Helpers::AttrPercent;
13 use SL::DB::Helpers::Metadata;
14 use SL::DB::Helpers::Manager;
15
16 use base qw(Rose::DB::Object);
17
18 sub new {
19   my $class = shift;
20   my $self  = $class->SUPER::new();
21
22   $self->_assign_attributes(@_) if $self;
23
24   return $self;
25 }
26
27 sub init_db {
28   my $class_or_self = shift;
29   my $class         = ref($class_or_self) || $class_or_self;
30   my $type          = 'LXOFFICE';
31
32   return SL::DB::create(undef, $type);
33 }
34
35 sub meta_class {
36   return 'SL::DB::Helpers::Metadata';
37 }
38
39 sub _get_manager_class {
40   my $class_or_self = shift;
41   my $class         = ref($class_or_self) || $class_or_self;
42
43   return $class->meta->convention_manager->auto_manager_class_name($class);
44 }
45
46 Readonly my %text_column_types => (text => 1, char => 1, varchar => 1);
47
48 sub assign_attributes {
49   my $self       = shift;
50   my %attributes = @_;
51
52   my $pk         = ref($self)->meta->primary_key;
53   delete @attributes{$pk->column_names} if $pk;
54
55   return $self->_assign_attributes(%attributes);
56 }
57
58 sub _assign_attributes {
59   my $self       = shift;
60   my %attributes = @_;
61
62   my %types      = map { $_->name => $_->type } ref($self)->meta->columns;
63
64   while (my ($attribute, $value) = each %attributes) {
65     my $type = lc($types{$attribute} || 'text');
66     $value   = $type eq 'boolean'        ? ($value ? 't' : 'f')
67              : $text_column_types{$type} ? $value
68              :                             ($value || undef);
69     $self->$attribute($value);
70   }
71
72   return $self;
73 }
74
75 sub update_attributes {
76   my $self = shift;
77
78   $self->assign_attributes(@_)->save;
79
80   return $self;
81 }
82
83 sub attr_number {
84   SL::DB::Helpers::AttrNumber::define(@_);
85 }
86
87 sub attr_date {
88   SL::DB::Helpers::AttrDate::define(@_);
89 }
90
91 sub attr_percent {
92   SL::DB::Helpers::AttrPercent::define(@_);
93 }
94
95 1;
96
97 __END__
98
99 =pod
100
101 =head1 NAME
102
103 SL::DB::Object: Base class for all of our model classes
104
105 =head1 DESCRIPTION
106
107 This is the base class from which all other model classes are
108 derived. It contains functionality and settings required for all model
109 classes.
110
111 Several functions (e.g. C<make_manager_class>, C<init_db>) in this
112 class are used for setting up the classes / base classes used for all
113 model instances. They overwrite the functions from
114 L<Rose::DB::Object>.
115
116 =head1 FUNCTIONS
117
118 =over 4
119
120 =item assign_attributes %attributes
121
122 =item _assign_attributes %attributes
123
124 Assigns all elements from C<%attributes> to the columns by calling
125 their setter functions. The difference between the two functions is
126 that C<assign_attributes> protects primary key columns while
127 C<_assign_attributes> doesn't.
128
129 Both functions handle values that are empty strings by replacing them
130 with C<undef> for non-text columns. This allows the calling functions
131 to use data from HTML forms as the input for C<assign_attributes>
132 without having to remove empty strings themselves (think of
133 e.g. select boxes with an empty option which should be turned into
134 C<NULL> in the database).
135
136 =item update_attributes %attributes
137
138 Assigns the attributes from C<%attributes> by calling the
139 C<assign_attributes> function and saves the object afterwards. Returns
140 the object itself.
141
142 =item _get_manager_class
143
144 Returns the manager package for the object or class that it is called
145 on. Can be used from methods in this package for getting the actual
146 object's manager.
147
148 =back
149
150 =head1 AUTHOR
151
152 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
153
154 =cut