Merge remote branch 'kc/new/enh/bug_5432' into kcmaster
[koha.git] / C4 / Members / AttributeTypes.pm
1 package C4::Members::AttributeTypes;
2
3 # Copyright (C) 2008 LibLime
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 use strict;
21 #use warnings; FIXME - Bug 2505
22 use C4::Context;
23
24 use vars qw($VERSION);
25
26 BEGIN {
27     # set the version for version checking
28     $VERSION = 3.00;
29 }
30
31 =head1 NAME
32
33 C4::Members::AttributeTypes - mananage extended patron attribute types
34
35 =head1 SYNOPSIS
36
37   my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes();
38
39   my $attr_type = C4::Members::AttributeTypes->new($code, $description);
40   $attr_type->code($code);
41   $attr_type->description($description);
42   $attr_type->repeatable($repeatable);
43   $attr_type->unique_id($unique_id);
44   $attr_type->opac_display($opac_display);
45   $attr_type->password_allowed($password_allowed);
46   $attr_type->staff_searchable($staff_searchable);
47   $attr_type->authorised_value_category($authorised_value_category);
48   $attr_type->store();
49   $attr_type->delete();
50
51   my $attr_type = C4::Members::AttributeTypes->fetch($code);
52   $attr_type = C4::Members::AttributeTypes->delete($code);
53
54 =head1 FUNCTIONS
55
56 =head2 GetAttributeTypes
57
58   my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes($all_fields);
59
60 Returns an array of hashrefs of each attribute type defined
61 in the database.  The array is sorted by code.  Each hashref contains
62 at least the following fields:
63
64  - code
65  - description
66
67 If $all_fields is true, then each hashref also contains the other fields from borrower_attribute_types.
68
69 =cut
70
71 sub GetAttributeTypes {
72     my $all = @_ ? shift : 0;
73     my $select = $all ? '*' : 'code, description';
74     my $dbh = C4::Context->dbh;
75     my $sth = $dbh->prepare("SELECT $select FROM borrower_attribute_types ORDER by code");
76     $sth->execute();
77     my $results = $sth->fetchall_arrayref({});
78     return @$results;
79 }
80
81 sub GetAttributeTypes_hashref {
82     my %hash = map {$_->{code} => $_} GetAttributeTypes(@_);
83     return \%hash;
84 }
85
86 =head1 METHODS 
87
88   my $attr_type = C4::Members::AttributeTypes->new($code, $description);
89
90 Create a new attribute type.
91
92 =cut 
93
94 sub new {
95     my $class = shift;
96     my $self = {};
97
98     $self->{'code'} = shift;
99     $self->{'description'} = shift;
100     $self->{'repeatable'} = 0;
101     $self->{'unique_id'} = 0;
102     $self->{'opac_display'} = 0;
103     $self->{'password_allowed'} = 0;
104     $self->{'staff_searchable'} = 0;
105     $self->{'authorised_value_category'} = '';
106
107     bless $self, $class;
108     return $self;
109 }
110
111 =head2 fetch
112
113   my $attr_type = C4::Members::AttributeTypes->fetch($code);
114
115 Fetches an attribute type from the database.  If no
116 type with the given C<$code> exists, returns undef.
117
118 =cut
119
120 sub fetch {
121     my $class = shift;
122     my $code = shift;
123     my $self = {};
124     my $dbh = C4::Context->dbh();
125
126     my $sth = $dbh->prepare_cached("SELECT * FROM borrower_attribute_types WHERE code = ?");
127     $sth->execute($code);
128     my $row = $sth->fetchrow_hashref;
129     $sth->finish();
130     return undef unless defined $row;    
131
132     $self->{'code'}                      = $row->{'code'};
133     $self->{'description'}               = $row->{'description'};
134     $self->{'repeatable'}                = $row->{'repeatable'};
135     $self->{'unique_id'}                 = $row->{'unique_id'};
136     $self->{'opac_display'}              = $row->{'opac_display'};
137     $self->{'password_allowed'}          = $row->{'password_allowed'};
138     $self->{'staff_searchable'}          = $row->{'staff_searchable'};
139     $self->{'authorised_value_category'} = $row->{'authorised_value_category'};
140
141     bless $self, $class;
142     return $self;
143 }
144
145 =head2 store
146
147   $attr_type->store();
148
149 Stores attribute type in the database.  If the type
150 previously retrieved from the database via the fetch()
151 method, the DB representation of the type is replaced.
152
153 =cut
154
155 sub store {
156     my $self = shift;
157
158     my $dbh = C4::Context->dbh;
159     my $sth;
160     my $existing = __PACKAGE__->fetch($self->{'code'});
161     if (defined $existing) {
162         $sth = $dbh->prepare_cached("UPDATE borrower_attribute_types
163                                      SET description = ?,
164                                          repeatable = ?,
165                                          unique_id = ?,
166                                          opac_display = ?,
167                                          password_allowed = ?,
168                                          staff_searchable = ?,
169                                          authorised_value_category = ?
170                                      WHERE code = ?");
171     } else {
172         $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types 
173                                         (description, repeatable, unique_id, opac_display, password_allowed,
174                                          staff_searchable, authorised_value_category, code)
175                                         VALUES (?, ?, ?, ?, ?,
176                                                 ?, ?, ?)");
177     }
178     $sth->bind_param(1, $self->{'description'});
179     $sth->bind_param(2, $self->{'repeatable'});
180     $sth->bind_param(3, $self->{'unique_id'});
181     $sth->bind_param(4, $self->{'opac_display'});
182     $sth->bind_param(5, $self->{'password_allowed'});
183     $sth->bind_param(6, $self->{'staff_searchable'});
184     $sth->bind_param(7, $self->{'authorised_value_category'});
185     $sth->bind_param(8, $self->{'code'});
186     $sth->execute;
187
188 }
189
190 =head2 code
191
192   my $code = $attr_type->code();
193   $attr_type->code($code);
194
195 Accessor.  Note that the code is immutable once
196 a type is created or fetched from the database.
197
198 =cut
199
200 sub code {
201     my $self = shift;
202     return $self->{'code'};
203 }
204
205 =head2 description
206
207   my $description = $attr_type->description();
208   $attr_type->description($description);
209
210 Accessor.
211
212 =cut
213
214 sub description {
215     my $self = shift;
216     @_ ? $self->{'description'} = shift : $self->{'description'};
217 }
218
219 =head2 repeatable
220
221   my $repeatable = $attr_type->repeatable();
222   $attr_type->repeatable($repeatable);
223
224 Accessor.  The C<$repeatable> argument
225 is interpreted as a Perl boolean.
226
227 =cut
228
229 sub repeatable {
230     my $self = shift;
231     @_ ? $self->{'repeatable'} = ((shift) ? 1 : 0) : $self->{'repeatable'};
232 }
233
234 =head2 unique_id
235
236   my $unique_id = $attr_type->unique_id();
237   $attr_type->unique_id($unique_id);
238
239 Accessor.  The C<$unique_id> argument
240 is interpreted as a Perl boolean.
241
242 =cut
243
244 sub unique_id {
245     my $self = shift;
246     @_ ? $self->{'unique_id'} = ((shift) ? 1 : 0) : $self->{'unique_id'};
247 }
248 =head2 opac_display
249
250   my $opac_display = $attr_type->opac_display();
251   $attr_type->opac_display($opac_display);
252
253 Accessor.  The C<$opac_display> argument
254 is interpreted as a Perl boolean.
255
256 =cut
257
258 sub opac_display {
259     my $self = shift;
260     @_ ? $self->{'opac_display'} = ((shift) ? 1 : 0) : $self->{'opac_display'};
261 }
262 =head2 password_allowed
263
264   my $password_allowed = $attr_type->password_allowed();
265   $attr_type->password_allowed($password_allowed);
266
267 Accessor.  The C<$password_allowed> argument
268 is interpreted as a Perl boolean.
269
270 =cut
271
272 sub password_allowed {
273     my $self = shift;
274     @_ ? $self->{'password_allowed'} = ((shift) ? 1 : 0) : $self->{'password_allowed'};
275 }
276 =head2 staff_searchable
277
278   my $staff_searchable = $attr_type->staff_searchable();
279   $attr_type->staff_searchable($staff_searchable);
280
281 Accessor.  The C<$staff_searchable> argument
282 is interpreted as a Perl boolean.
283
284 =cut
285
286 sub staff_searchable {
287     my $self = shift;
288     @_ ? $self->{'staff_searchable'} = ((shift) ? 1 : 0) : $self->{'staff_searchable'};
289 }
290
291 =head2 authorised_value_category
292
293   my $authorised_value_category = $attr_type->authorised_value_category();
294   $attr_type->authorised_value_category($authorised_value_category);
295
296 Accessor.
297
298 =cut
299
300 sub authorised_value_category {
301     my $self = shift;
302     @_ ? $self->{'authorised_value_category'} = shift : $self->{'authorised_value_category'};
303 }
304
305 =head2 delete
306
307   $attr_type->delete();
308   C4::Members::AttributeTypes->delete($code);
309
310 Delete an attribute type from the database.  The attribute
311 type may be specified either by an object or by a code.
312
313 =cut
314
315 sub delete {
316     my $arg = shift;
317     my $code;
318     if (ref($arg) eq __PACKAGE__) {
319         $code = $arg->{'code'};
320     } else {
321         $code = shift;
322     }
323
324     my $dbh = C4::Context->dbh;
325     my $sth = $dbh->prepare_cached("DELETE FROM borrower_attribute_types WHERE code = ?");
326     $sth->execute($code);
327 }
328
329 =head2 num_patrons
330
331   my $count = $attr_type->num_patrons();
332
333 Returns the number of patron records that use
334 this attribute type.
335
336 =cut
337
338 sub num_patrons {
339     my $self = shift;
340
341     my $dbh = C4::Context->dbh;
342     my $sth = $dbh->prepare_cached("SELECT COUNT(DISTINCT borrowernumber)
343                                     FROM borrower_attributes
344                                     WHERE code = ?");
345     $sth->execute($self->{code});
346     my ($count) = $sth->fetchrow_array;
347     $sth->finish;
348     return $count;
349 }
350
351 =head2 get_patrons
352
353   my @borrowernumbers = $attr_type->get_patrons($attribute);
354
355 Returns the borrowernumber of the patron records that
356 have an attribute with the specifie value.
357
358 =cut
359
360 sub get_patrons {
361     my $self = shift;
362     my $value = shift;
363
364     my $dbh = C4::Context->dbh;
365     my $sth = $dbh->prepare_cached("SELECT DISTINCT borrowernumber
366                                     FROM borrower_attributes
367                                     WHERE code = ?
368                                     AND   attribute = ?");
369     $sth->execute($self->{code}, $value);
370     my @results;
371     while (my ($borrowernumber) = $sth->fetchrow_array) {
372         push @results, $borrowernumber;
373     } 
374     return @results;
375 }
376
377 =head1 AUTHOR
378
379 Koha Development Team <http://koha-community.org/>
380
381 Galen Charlton <galen.charlton@liblime.com>
382
383 =cut
384
385 1;