Merge remote-tracking branch 'kc/new/bug_5995' 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) = @_;
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 =head2 AttributeTypeExists
87
88   my $have_attr_xyz = C4::Members::AttributeTypes::AttributeTypeExists($code)
89
90 Returns true if we have attribute type C<$code>
91 in the database.
92
93 =cut
94
95 sub AttributeTypeExists {
96     my ($code) = @_;
97     my $dbh = C4::Context->dbh;
98     my $exists = $dbh->selectrow_array("SELECT code FROM borrower_attribute_types WHERE code = ?", undef, $code);
99     return $exists;
100 }
101
102 =head1 METHODS 
103
104   my $attr_type = C4::Members::AttributeTypes->new($code, $description);
105
106 Create a new attribute type.
107
108 =cut 
109
110 sub new {
111     my $class = shift;
112     my $self = {};
113
114     $self->{'code'} = shift;
115     $self->{'description'} = shift;
116     $self->{'repeatable'} = 0;
117     $self->{'unique_id'} = 0;
118     $self->{'opac_display'} = 0;
119     $self->{'password_allowed'} = 0;
120     $self->{'staff_searchable'} = 0;
121     $self->{'display_checkout'} = 0;
122     $self->{'authorised_value_category'} = '';
123
124     bless $self, $class;
125     return $self;
126 }
127
128 =head2 fetch
129
130   my $attr_type = C4::Members::AttributeTypes->fetch($code);
131
132 Fetches an attribute type from the database.  If no
133 type with the given C<$code> exists, returns undef.
134
135 =cut
136
137 sub fetch {
138     my $class = shift;
139     my $code = shift;
140     my $self = {};
141     my $dbh = C4::Context->dbh();
142
143     my $sth = $dbh->prepare_cached("SELECT * FROM borrower_attribute_types WHERE code = ?");
144     $sth->execute($code);
145     my $row = $sth->fetchrow_hashref;
146     $sth->finish();
147     return undef unless defined $row;    
148
149     $self->{'code'}                      = $row->{'code'};
150     $self->{'description'}               = $row->{'description'};
151     $self->{'repeatable'}                = $row->{'repeatable'};
152     $self->{'unique_id'}                 = $row->{'unique_id'};
153     $self->{'opac_display'}              = $row->{'opac_display'};
154     $self->{'password_allowed'}          = $row->{'password_allowed'};
155     $self->{'staff_searchable'}          = $row->{'staff_searchable'};
156     $self->{'display_checkout'}          = $row->{'display_checkout'};
157     $self->{'authorised_value_category'} = $row->{'authorised_value_category'};
158
159     bless $self, $class;
160     return $self;
161 }
162
163 =head2 store
164
165   $attr_type->store();
166
167 Stores attribute type in the database.  If the type
168 previously retrieved from the database via the fetch()
169 method, the DB representation of the type is replaced.
170
171 =cut
172
173 sub store {
174     my $self = shift;
175
176     my $dbh = C4::Context->dbh;
177     my $sth;
178     my $existing = __PACKAGE__->fetch($self->{'code'});
179     if (defined $existing) {
180         $sth = $dbh->prepare_cached("UPDATE borrower_attribute_types
181                                      SET description = ?,
182                                          repeatable = ?,
183                                          unique_id = ?,
184                                          opac_display = ?,
185                                          password_allowed = ?,
186                                          staff_searchable = ?,
187                                          authorised_value_category = ?,
188                                          display_checkout = ?
189                                      WHERE code = ?");
190     } else {
191         $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types 
192                                         (description, repeatable, unique_id, opac_display, password_allowed,
193                                          staff_searchable, authorised_value_category, display_checkout, code)
194                                         VALUES (?, ?, ?, ?, ?,
195                                                 ?, ?, ?, ?)");
196     }
197     $sth->bind_param(1, $self->{'description'});
198     $sth->bind_param(2, $self->{'repeatable'});
199     $sth->bind_param(3, $self->{'unique_id'});
200     $sth->bind_param(4, $self->{'opac_display'});
201     $sth->bind_param(5, $self->{'password_allowed'});
202     $sth->bind_param(6, $self->{'staff_searchable'});
203     $sth->bind_param(7, $self->{'authorised_value_category'});
204     $sth->bind_param(8, $self->{'display_checkout'});
205     $sth->bind_param(9, $self->{'code'});
206     $sth->execute;
207
208 }
209
210 =head2 code
211
212   my $code = $attr_type->code();
213   $attr_type->code($code);
214
215 Accessor.  Note that the code is immutable once
216 a type is created or fetched from the database.
217
218 =cut
219
220 sub code {
221     my $self = shift;
222     return $self->{'code'};
223 }
224
225 =head2 description
226
227   my $description = $attr_type->description();
228   $attr_type->description($description);
229
230 Accessor.
231
232 =cut
233
234 sub description {
235     my $self = shift;
236     @_ ? $self->{'description'} = shift : $self->{'description'};
237 }
238
239 =head2 repeatable
240
241   my $repeatable = $attr_type->repeatable();
242   $attr_type->repeatable($repeatable);
243
244 Accessor.  The C<$repeatable> argument
245 is interpreted as a Perl boolean.
246
247 =cut
248
249 sub repeatable {
250     my $self = shift;
251     @_ ? $self->{'repeatable'} = ((shift) ? 1 : 0) : $self->{'repeatable'};
252 }
253
254 =head2 unique_id
255
256   my $unique_id = $attr_type->unique_id();
257   $attr_type->unique_id($unique_id);
258
259 Accessor.  The C<$unique_id> argument
260 is interpreted as a Perl boolean.
261
262 =cut
263
264 sub unique_id {
265     my $self = shift;
266     @_ ? $self->{'unique_id'} = ((shift) ? 1 : 0) : $self->{'unique_id'};
267 }
268 =head2 opac_display
269
270   my $opac_display = $attr_type->opac_display();
271   $attr_type->opac_display($opac_display);
272
273 Accessor.  The C<$opac_display> argument
274 is interpreted as a Perl boolean.
275
276 =cut
277
278 sub opac_display {
279     my $self = shift;
280     @_ ? $self->{'opac_display'} = ((shift) ? 1 : 0) : $self->{'opac_display'};
281 }
282 =head2 password_allowed
283
284   my $password_allowed = $attr_type->password_allowed();
285   $attr_type->password_allowed($password_allowed);
286
287 Accessor.  The C<$password_allowed> argument
288 is interpreted as a Perl boolean.
289
290 =cut
291
292 sub password_allowed {
293     my $self = shift;
294     @_ ? $self->{'password_allowed'} = ((shift) ? 1 : 0) : $self->{'password_allowed'};
295 }
296 =head2 staff_searchable
297
298   my $staff_searchable = $attr_type->staff_searchable();
299   $attr_type->staff_searchable($staff_searchable);
300
301 Accessor.  The C<$staff_searchable> argument
302 is interpreted as a Perl boolean.
303
304 =cut
305
306 sub staff_searchable {
307     my $self = shift;
308     @_ ? $self->{'staff_searchable'} = ((shift) ? 1 : 0) : $self->{'staff_searchable'};
309 }
310
311 =head2 display_checkout
312
313 =over 4
314
315 my $display_checkout = $attr_type->display_checkout();
316 $attr_type->display_checkout($display_checkout);
317
318 =back
319
320 Accessor.  The C<$display_checkout> argument
321 is interpreted as a Perl boolean.
322
323 =cut
324
325 sub display_checkout {
326     my $self = shift;
327     @_ ? $self->{'display_checkout'} = ((shift) ? 1 : 0) : $self->{'display_checkout'};
328 }
329
330 =head2 authorised_value_category
331
332   my $authorised_value_category = $attr_type->authorised_value_category();
333   $attr_type->authorised_value_category($authorised_value_category);
334
335 Accessor.
336
337 =cut
338
339 sub authorised_value_category {
340     my $self = shift;
341     @_ ? $self->{'authorised_value_category'} = shift : $self->{'authorised_value_category'};
342 }
343
344 =head2 delete
345
346   $attr_type->delete();
347   C4::Members::AttributeTypes->delete($code);
348
349 Delete an attribute type from the database.  The attribute
350 type may be specified either by an object or by a code.
351
352 =cut
353
354 sub delete {
355     my $arg = shift;
356     my $code;
357     if (ref($arg) eq __PACKAGE__) {
358         $code = $arg->{'code'};
359     } else {
360         $code = shift;
361     }
362
363     my $dbh = C4::Context->dbh;
364     my $sth = $dbh->prepare_cached("DELETE FROM borrower_attribute_types WHERE code = ?");
365     $sth->execute($code);
366 }
367
368 =head2 num_patrons
369
370   my $count = $attr_type->num_patrons();
371
372 Returns the number of patron records that use
373 this attribute type.
374
375 =cut
376
377 sub num_patrons {
378     my $self = shift;
379
380     my $dbh = C4::Context->dbh;
381     my $sth = $dbh->prepare_cached("SELECT COUNT(DISTINCT borrowernumber)
382                                     FROM borrower_attributes
383                                     WHERE code = ?");
384     $sth->execute($self->{code});
385     my ($count) = $sth->fetchrow_array;
386     $sth->finish;
387     return $count;
388 }
389
390 =head2 get_patrons
391
392   my @borrowernumbers = $attr_type->get_patrons($attribute);
393
394 Returns the borrowernumber of the patron records that
395 have an attribute with the specifie value.
396
397 =cut
398
399 sub get_patrons {
400     my $self = shift;
401     my $value = shift;
402
403     my $dbh = C4::Context->dbh;
404     my $sth = $dbh->prepare_cached("SELECT DISTINCT borrowernumber
405                                     FROM borrower_attributes
406                                     WHERE code = ?
407                                     AND   attribute = ?");
408     $sth->execute($self->{code}, $value);
409     my @results;
410     while (my ($borrowernumber) = $sth->fetchrow_array) {
411         push @results, $borrowernumber;
412     } 
413     return @results;
414 }
415
416 =head1 AUTHOR
417
418 Koha Development Team <http://koha-community.org/>
419
420 Galen Charlton <galen.charlton@liblime.com>
421
422 =cut
423
424 1;