Bug 16011: $VERSION - Remove the $VERSION init
[koha.git] / C4 / Members / AttributeTypes.pm
blobfe5be4e5890a88cb3d3a139a74e064ed1aa33f3f
1 package C4::Members::AttributeTypes;
3 # Copyright (C) 2008 LibLime
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use strict;
21 #use warnings; FIXME - Bug 2505
22 use C4::Context;
24 use vars qw();
26 BEGIN {
27 # set the version for version checking
30 =head1 NAME
32 C4::Members::AttributeTypes - mananage extended patron attribute types
34 =head1 SYNOPSIS
36 my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes();
38 my $attr_type = C4::Members::AttributeTypes->new($code, $description);
39 $attr_type->code($code);
40 $attr_type->description($description);
41 $attr_type->repeatable($repeatable);
42 $attr_type->unique_id($unique_id);
43 $attr_type->opac_display($opac_display);
44 $attr_type->password_allowed($password_allowed);
45 $attr_type->staff_searchable($staff_searchable);
46 $attr_type->authorised_value_category($authorised_value_category);
47 $attr_type->store();
48 $attr_type->delete();
50 my $attr_type = C4::Members::AttributeTypes->fetch($code);
51 $attr_type = C4::Members::AttributeTypes->delete($code);
53 =head1 FUNCTIONS
55 =head2 GetAttributeTypes
57 my @attribute_types = C4::Members::AttributeTypes::GetAttributeTypes($all_fields);
59 Returns an array of hashrefs of each attribute type defined
60 in the database. The array is sorted by code. Each hashref contains
61 at least the following fields:
63 - code
64 - description
66 If $all_fields is true, then each hashref also contains the other fields from borrower_attribute_types.
68 =cut
70 sub GetAttributeTypes {
71 my $all = @_ ? shift : 0;
72 my $no_branch_limit = @_ ? shift : 0;
73 my $branch_limit = $no_branch_limit
74 ? 0
75 : C4::Context->userenv ? C4::Context->userenv->{"branch"} : 0;
76 my $select = $all ? '*' : 'DISTINCT(code), description, class';
78 my $dbh = C4::Context->dbh;
79 my $query = "SELECT $select FROM borrower_attribute_types";
80 $query .= qq{
81 LEFT JOIN borrower_attribute_types_branches ON bat_code = code
82 WHERE b_branchcode = ? OR b_branchcode IS NULL
83 } if $branch_limit;
84 $query .= " ORDER BY code";
85 my $sth = $dbh->prepare($query);
86 $sth->execute( $branch_limit ? $branch_limit : () );
87 my $results = $sth->fetchall_arrayref({});
88 $sth->finish;
89 return @$results;
92 sub GetAttributeTypes_hashref {
93 my %hash = map {$_->{code} => $_} GetAttributeTypes(@_);
94 return \%hash;
97 =head2 AttributeTypeExists
99 my $have_attr_xyz = C4::Members::AttributeTypes::AttributeTypeExists($code)
101 Returns true if we have attribute type C<$code>
102 in the database.
104 =cut
106 sub AttributeTypeExists {
107 my ($code) = @_;
108 my $dbh = C4::Context->dbh;
109 my $exists = $dbh->selectrow_array("SELECT code FROM borrower_attribute_types WHERE code = ?", undef, $code);
110 return $exists;
113 =head1 METHODS
115 my $attr_type = C4::Members::AttributeTypes->new($code, $description);
117 Create a new attribute type.
119 =cut
121 sub new {
122 my $class = shift;
123 my $self = {};
125 $self->{'code'} = shift;
126 $self->{'description'} = shift;
127 $self->{'repeatable'} = 0;
128 $self->{'unique_id'} = 0;
129 $self->{'opac_display'} = 0;
130 $self->{'password_allowed'} = 0;
131 $self->{'staff_searchable'} = 0;
132 $self->{'display_checkout'} = 0;
133 $self->{'authorised_value_category'} = '';
134 $self->{'category_code'} = '';
135 $self->{'category_description'} = '';
136 $self->{'class'} = '';
138 bless $self, $class;
139 return $self;
142 =head2 fetch
144 my $attr_type = C4::Members::AttributeTypes->fetch($code);
146 Fetches an attribute type from the database. If no
147 type with the given C<$code> exists, returns undef.
149 =cut
151 sub fetch {
152 my $class = shift;
153 my $code = shift;
154 my $self = {};
155 my $dbh = C4::Context->dbh();
157 my $sth = $dbh->prepare_cached("
158 SELECT borrower_attribute_types.*, categories.description AS category_description
159 FROM borrower_attribute_types
160 LEFT JOIN categories ON borrower_attribute_types.category_code=categories.categorycode
161 WHERE code =?");
162 $sth->execute($code);
163 my $row = $sth->fetchrow_hashref;
164 $sth->finish();
165 return unless defined $row;
167 $self->{'code'} = $row->{'code'};
168 $self->{'description'} = $row->{'description'};
169 $self->{'repeatable'} = $row->{'repeatable'};
170 $self->{'unique_id'} = $row->{'unique_id'};
171 $self->{'opac_display'} = $row->{'opac_display'};
172 $self->{'password_allowed'} = $row->{'password_allowed'};
173 $self->{'staff_searchable'} = $row->{'staff_searchable'};
174 $self->{'display_checkout'} = $row->{'display_checkout'};
175 $self->{'authorised_value_category'} = $row->{'authorised_value_category'};
176 $self->{'category_code'} = $row->{'category_code'};
177 $self->{'category_description'} = $row->{'category_description'};
178 $self->{'class'} = $row->{'class'};
180 $sth = $dbh->prepare("SELECT branchcode, branchname FROM borrower_attribute_types_branches, branches WHERE b_branchcode = branchcode AND bat_code = ?;");
181 $sth->execute( $code );
182 while ( my $data = $sth->fetchrow_hashref ) {
183 push @{ $self->{branches} }, $data;
185 $sth->finish();
187 bless $self, $class;
188 return $self;
191 =head2 store
193 $attr_type->store();
195 Stores attribute type in the database. If the type
196 previously retrieved from the database via the fetch()
197 method, the DB representation of the type is replaced.
199 =cut
201 sub store {
202 my $self = shift;
204 my $dbh = C4::Context->dbh;
205 my $sth;
206 my $existing = __PACKAGE__->fetch($self->{'code'});
207 if (defined $existing) {
208 $sth = $dbh->prepare_cached("UPDATE borrower_attribute_types
209 SET description = ?,
210 repeatable = ?,
211 unique_id = ?,
212 opac_display = ?,
213 password_allowed = ?,
214 staff_searchable = ?,
215 authorised_value_category = ?,
216 display_checkout = ?,
217 category_code = ?,
218 class = ?
219 WHERE code = ?");
220 } else {
221 $sth = $dbh->prepare_cached("INSERT INTO borrower_attribute_types
222 (description, repeatable, unique_id, opac_display, password_allowed,
223 staff_searchable, authorised_value_category, display_checkout, category_code, class, code)
224 VALUES (?, ?, ?, ?, ?,
225 ?, ?, ?, ?, ?, ?)");
227 $sth->bind_param(1, $self->{'description'});
228 $sth->bind_param(2, $self->{'repeatable'});
229 $sth->bind_param(3, $self->{'unique_id'});
230 $sth->bind_param(4, $self->{'opac_display'});
231 $sth->bind_param(5, $self->{'password_allowed'});
232 $sth->bind_param(6, $self->{'staff_searchable'});
233 $sth->bind_param(7, $self->{'authorised_value_category'});
234 $sth->bind_param(8, $self->{'display_checkout'});
235 $sth->bind_param(9, $self->{'category_code'} || undef);
236 $sth->bind_param(10, $self->{'class'});
237 $sth->bind_param(11, $self->{'code'});
238 $sth->execute;
240 if ( defined $$self{branches} ) {
241 $sth = $dbh->prepare("DELETE FROM borrower_attribute_types_branches WHERE bat_code = ?");
242 $sth->execute( $$self{code} );
243 $sth = $dbh->prepare(
244 "INSERT INTO borrower_attribute_types_branches
245 ( bat_code, b_branchcode )
246 VALUES ( ?, ? )"
248 for my $branchcode ( @{$$self{branches}} ) {
249 next if not $branchcode;
250 $sth->bind_param( 1, $$self{code} );
251 $sth->bind_param( 2, $branchcode );
252 $sth->execute;
255 $sth->finish;
258 =head2 code
260 my $code = $attr_type->code();
261 $attr_type->code($code);
263 Accessor. Note that the code is immutable once
264 a type is created or fetched from the database.
266 =cut
268 sub code {
269 my $self = shift;
270 return $self->{'code'};
273 =head2 description
275 my $description = $attr_type->description();
276 $attr_type->description($description);
278 Accessor.
280 =cut
282 sub description {
283 my $self = shift;
284 @_ ? $self->{'description'} = shift : $self->{'description'};
287 =head2 branches
289 my $branches = $attr_type->branches();
290 $attr_type->branches($branches);
292 Accessor.
294 =cut
296 sub branches {
297 my $self = shift;
298 @_ ? $self->{branches} = shift : $self->{branches};
301 =head2 repeatable
303 my $repeatable = $attr_type->repeatable();
304 $attr_type->repeatable($repeatable);
306 Accessor. The C<$repeatable> argument
307 is interpreted as a Perl boolean.
309 =cut
311 sub repeatable {
312 my $self = shift;
313 @_ ? $self->{'repeatable'} = ((shift) ? 1 : 0) : $self->{'repeatable'};
316 =head2 unique_id
318 my $unique_id = $attr_type->unique_id();
319 $attr_type->unique_id($unique_id);
321 Accessor. The C<$unique_id> argument
322 is interpreted as a Perl boolean.
324 =cut
326 sub unique_id {
327 my $self = shift;
328 @_ ? $self->{'unique_id'} = ((shift) ? 1 : 0) : $self->{'unique_id'};
330 =head2 opac_display
332 my $opac_display = $attr_type->opac_display();
333 $attr_type->opac_display($opac_display);
335 Accessor. The C<$opac_display> argument
336 is interpreted as a Perl boolean.
338 =cut
340 sub opac_display {
341 my $self = shift;
342 @_ ? $self->{'opac_display'} = ((shift) ? 1 : 0) : $self->{'opac_display'};
344 =head2 password_allowed
346 my $password_allowed = $attr_type->password_allowed();
347 $attr_type->password_allowed($password_allowed);
349 Accessor. The C<$password_allowed> argument
350 is interpreted as a Perl boolean.
352 =cut
354 sub password_allowed {
355 my $self = shift;
356 @_ ? $self->{'password_allowed'} = ((shift) ? 1 : 0) : $self->{'password_allowed'};
358 =head2 staff_searchable
360 my $staff_searchable = $attr_type->staff_searchable();
361 $attr_type->staff_searchable($staff_searchable);
363 Accessor. The C<$staff_searchable> argument
364 is interpreted as a Perl boolean.
366 =cut
368 sub staff_searchable {
369 my $self = shift;
370 @_ ? $self->{'staff_searchable'} = ((shift) ? 1 : 0) : $self->{'staff_searchable'};
373 =head2 display_checkout
375 my $display_checkout = $attr_type->display_checkout();
376 $attr_type->display_checkout($display_checkout);
378 Accessor. The C<$display_checkout> argument
379 is interpreted as a Perl boolean.
381 =cut
383 sub display_checkout {
384 my $self = shift;
385 @_ ? $self->{'display_checkout'} = ((shift) ? 1 : 0) : $self->{'display_checkout'};
388 =head2 authorised_value_category
390 my $authorised_value_category = $attr_type->authorised_value_category();
391 $attr_type->authorised_value_category($authorised_value_category);
393 Accessor.
395 =cut
397 sub authorised_value_category {
398 my $self = shift;
399 @_ ? $self->{'authorised_value_category'} = shift : $self->{'authorised_value_category'};
402 =head2 category_code
404 my $category_code = $attr_type->category_code();
405 $attr_type->category_code($category_code);
407 Accessor.
409 =cut
411 sub category_code {
412 my $self = shift;
413 @_ ? $self->{'category_code'} = shift : $self->{'category_code'};
416 =head2 category_description
418 my $category_description = $attr_type->category_description();
419 $attr_type->category_description($category_description);
421 Accessor.
423 =cut
425 sub category_description {
426 my $self = shift;
427 @_ ? $self->{'category_description'} = shift : $self->{'category_description'};
430 =head2 class
432 my $class = $attr_type->class();
433 $attr_type->class($class);
435 Accessor.
437 =cut
439 sub class {
440 my $self = shift;
441 @_ ? $self->{'class'} = shift : $self->{'class'};
445 =head2 delete
447 $attr_type->delete();
448 C4::Members::AttributeTypes->delete($code);
450 Delete an attribute type from the database. The attribute
451 type may be specified either by an object or by a code.
453 =cut
455 sub delete {
456 my $arg = shift;
457 my $code;
458 if (ref($arg) eq __PACKAGE__) {
459 $code = $arg->{'code'};
460 } else {
461 $code = shift;
464 my $dbh = C4::Context->dbh;
465 my $sth = $dbh->prepare_cached("DELETE FROM borrower_attribute_types WHERE code = ?");
466 $sth->execute($code);
467 $sth->finish;
470 =head2 num_patrons
472 my $count = $attr_type->num_patrons();
474 Returns the number of patron records that use
475 this attribute type.
477 =cut
479 sub num_patrons {
480 my $self = shift;
482 my $dbh = C4::Context->dbh;
483 my $sth = $dbh->prepare_cached("SELECT COUNT(DISTINCT borrowernumber)
484 FROM borrower_attributes
485 WHERE code = ?");
486 $sth->execute($self->{code});
487 my ($count) = $sth->fetchrow_array;
488 $sth->finish;
489 return $count;
492 =head2 get_patrons
494 my @borrowernumbers = $attr_type->get_patrons($attribute);
496 Returns the borrowernumber of the patron records that
497 have an attribute with the specifie value.
499 =cut
501 sub get_patrons {
502 my $self = shift;
503 my $value = shift;
505 my $dbh = C4::Context->dbh;
506 my $sth = $dbh->prepare_cached("SELECT DISTINCT borrowernumber
507 FROM borrower_attributes
508 WHERE code = ?
509 AND attribute = ?");
510 $sth->execute($self->{code}, $value);
511 my @results;
512 while (my ($borrowernumber) = $sth->fetchrow_array) {
513 push @results, $borrowernumber;
515 return @results;
518 =head1 AUTHOR
520 Koha Development Team <http://koha-community.org/>
522 Galen Charlton <galen.charlton@liblime.com>
524 =cut