Bug 36982: Collections facet does not get alphabetized based on collection descriptions
[koha.git] / Koha / Library.pm
1 package Koha::Library;
2
3 # Copyright 2015 Koha Development team
4 #
5 # This file is part of Koha.
6 #
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.
11 #
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.
16 #
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>.
19
20 use Modern::Perl;
21
22
23 use C4::Context;
24
25 use Koha::Caches;
26 use Koha::Database;
27 use Koha::Desks;
28 use Koha::StockRotationStages;
29 use Koha::SMTP::Servers;
30 use Koha::Library::Hours;
31
32 use base qw(Koha::Object);
33
34 my $cache = Koha::Caches->get_instance();
35
36 =head1 NAME
37
38 Koha::Library - Koha Library Object class
39
40 =head1 API
41
42 =head2 Class methods
43
44 =head3 store
45
46 Library specific store to ensure relevant caches are flushed on change
47
48 =cut
49
50 sub store {
51     my ($self) = @_;
52
53     my $flush = 0;
54
55     if ( !$self->in_storage ) {
56         $flush = 1;
57     }
58     else {
59         my $self_from_storage = $self->get_from_storage;
60         $flush = 1 if ( $self_from_storage->branchname ne $self->branchname );
61     }
62
63     $self = $self->SUPER::store;
64
65     if ($flush) {
66         $cache->clear_from_cache('libraries:name');
67     }
68
69     return $self;
70 }
71
72 =head2 delete
73
74 Library specific C<delete> to clear relevant caches on delete.
75
76 =cut
77
78 sub delete {
79     my $self = shift @_;
80     $cache->clear_from_cache('libraries:name');
81     $self->SUPER::delete(@_);
82 }
83
84 =head3 stockrotationstages
85
86   my $stages = Koha::Library->stockrotationstages;
87
88 Returns the stockrotation stages associated with this Library.
89
90 =cut
91
92 sub stockrotationstages {
93     my ( $self ) = @_;
94     my $rs = $self->_result->stockrotationstages;
95     return Koha::StockRotationStages->_new_from_dbic( $rs );
96 }
97
98 =head3 outgoing_transfers
99
100   my $outgoing_transfers = Koha::Library->outgoing_transfers;
101
102 Returns the outgoing item transfers associated with this Library.
103
104 =cut
105
106 sub outgoing_transfers {
107     my ( $self ) = @_;
108     my $rs = $self->_result->branchtransfers_frombranches;
109     return Koha::Item::Transfers->_new_from_dbic( $rs );
110 }
111
112 =head3 inbound_transfers
113
114   my $inbound_transfers = Koha::Library->inbound_transfers;
115
116 Returns the inbound item transfers associated with this Library.
117
118 =cut
119
120 sub inbound_transfers {
121     my ( $self ) = @_;
122     my $rs = $self->_result->branchtransfers_tobranches;
123     return Koha::Item::Transfers->_new_from_dbic( $rs );
124 }
125
126 =head3 get_effective_marcorgcode
127
128     my $marcorgcode = Koha::Libraries->find( $library_id )->get_effective_marcorgcode();
129
130 Returns the effective MARC organization code of the library. It falls back to the value
131 from the I<MARCOrgCode> syspref if undefined for the library.
132
133 =cut
134
135 sub get_effective_marcorgcode {
136     my ( $self )  = @_;
137
138     return $self->marcorgcode || C4::Context->preference("MARCOrgCode");
139 }
140
141 =head3 smtp_server
142
143     my $smtp_server = $library->smtp_server;
144     $library->smtp_server({ smtp_server => $smtp_server });
145     $library->smtp_server({ smtp_server => undef });
146
147 Accessor for getting and setting the library's SMTP server.
148
149 Returns the effective SMTP server configuration to be used on the library. The returned
150 value is always a I<Koha::SMTP::Server> object.
151
152 Setting it to undef will remove the link to a specific SMTP server and effectively
153 make the library use the default setting
154
155 =cut
156
157 sub smtp_server {
158     my ( $self, $params ) = @_;
159
160     my $library_smtp_server_rs = $self->_result->library_smtp_server;
161
162     if ( exists $params->{smtp_server} ) {
163
164         $self->_result->result_source->schema->txn_do( sub {
165             $library_smtp_server_rs->delete
166                 if $library_smtp_server_rs;
167
168             if ( defined $params->{smtp_server} ) {
169                 # Set the new server
170                 # Remove any already set SMTP server
171
172                 my $smtp_server = $params->{smtp_server};
173                 $smtp_server->_result->add_to_library_smtp_servers({ library_id => $self->id });
174             }
175         });
176     } # else => reset to default
177     else {
178         # Getter
179         if ( $library_smtp_server_rs ) {
180             return Koha::SMTP::Servers->find(
181                 $library_smtp_server_rs->smtp_server_id );
182         }
183
184         return Koha::SMTP::Servers->get_default;
185     }
186
187     return $self;
188 }
189
190 =head3 from_email_address
191
192   my $from_email = Koha::Library->from_email_address;
193
194 Returns the official 'from' email address for the branch.
195
196 It may well be a 'noreply' or other inaccessible local domain
197 address that is being used to satisfy spam protection filters.
198
199 =cut
200
201 sub from_email_address {
202     my ($self) = @_;
203
204     return
205          $self->branchemail
206       || C4::Context->preference('KohaAdminEmailAddress')
207       || undef;
208 }
209
210 =head3 inbound_email_address
211
212   my $to_email = Koha::Library->inbound_email_address;
213
214 Returns an effective email address which should be accessible to librarians at the branch.
215
216 NOTE: This is the address to use for 'reply_to' or 'to' fields; It should not usually be
217 used as the 'from' address for emails as it may lead to mail being caught by spam filters.
218
219 =cut
220
221 sub inbound_email_address {
222     my ($self) = @_;
223
224     return
225          $self->branchreplyto
226       || $self->branchemail
227       || C4::Context->preference('ReplytoDefault')
228       || C4::Context->preference('KohaAdminEmailAddress')
229       || undef;
230 }
231
232 =head3 inbound_ill_address
233
234   my $to_email = Koha::Library->inbound_ill_address;
235
236 Returns an effective email address which should be accessible to librarians at the branch
237 for inter library loans communication.
238
239 =cut
240
241 sub inbound_ill_address {
242     my ($self) = @_;
243
244     return
245          $self->branchillemail
246       || C4::Context->preference('ILLDefaultStaffEmail')
247       || $self->inbound_email_address;
248 }
249
250 =head3 library_groups
251
252 Return the Library groups of this library
253
254 =cut
255
256 sub library_groups {
257     my ( $self ) = @_;
258     my $rs = $self->_result->library_groups;
259     return Koha::Library::Groups->_new_from_dbic( $rs );
260 }
261
262 =head3 cash_registers
263
264 Return Cash::Registers associated with this Library
265
266 =cut
267
268 sub cash_registers {
269     my ( $self ) = @_;
270     my $rs = $self->_result->cash_registers;
271     return Koha::Cash::Registers->_new_from_dbic( $rs );
272 }
273
274 =head3 desks
275
276     my $desks = $library->desks;
277
278 Returns Koha::Desks associated with this library.
279
280 =cut
281
282 sub desks {
283     my ($self) = @_;
284     return Koha::Desks->_new_from_dbic( scalar $self->_result->desks );
285 }
286
287 =head3 get_hold_libraries
288
289 Return all libraries (including self) that belong to the same hold groups
290
291 =cut
292
293 sub get_hold_libraries {
294     my ( $self ) = @_;
295     my $library_groups = $self->library_groups;
296     my @hold_libraries;
297     while ( my $library_group = $library_groups->next ) {
298         my $root = Koha::Library::Groups->get_root_ancestor({id => $library_group->id});
299         if($root->ft_local_hold_group) {
300             push @hold_libraries, $root->all_libraries;
301         }
302     }
303
304     my %seen;
305     @hold_libraries =
306       grep { !$seen{ $_->id }++ } @hold_libraries;
307
308     return Koha::Libraries->search({ branchcode => { '-in' => [ keys %seen ] } });
309 }
310
311 =head3 validate_hold_sibling
312
313 Return if given library is a valid hold group member
314
315 =cut
316
317 sub validate_hold_sibling {
318     my ( $self, $params ) = @_;
319
320     return 1 if $params->{branchcode} eq $self->id;
321
322     my $branchcode = $params->{branchcode};
323     return $self->get_hold_libraries->search( { branchcode => $branchcode } )
324       ->count > 0;
325 }
326
327 =head3 public_read_list
328
329 This method returns the list of publicly readable database fields for both API and UI output purposes
330
331 =cut
332
333 sub public_read_list {
334     return [
335         'branchcode',     'branchname',     'branchaddress1',
336         'branchaddress2', 'branchaddress3', 'branchzip',
337         'branchcity',     'branchstate',    'branchcountry',
338         'branchfax',      'branchemail',    'branchurl'
339     ];
340 }
341
342 =head3 to_api_mapping
343
344 This method returns the mapping for representing a Koha::Library object
345 on the API.
346
347 =cut
348
349 sub to_api_mapping {
350     return {
351         branchcode       => 'library_id',
352         branchname       => 'name',
353         branchaddress1   => 'address1',
354         branchaddress2   => 'address2',
355         branchaddress3   => 'address3',
356         branchzip        => 'postal_code',
357         branchcity       => 'city',
358         branchstate      => 'state',
359         branchcountry    => 'country',
360         branchphone      => 'phone',
361         branchfax        => 'fax',
362         branchemail      => 'email',
363         branchillemail   => 'illemail',
364         branchreplyto    => 'reply_to_email',
365         branchreturnpath => 'return_path_email',
366         branchurl        => 'url',
367         issuing          => undef,
368         branchip         => 'ip',
369         branchnotes      => 'notes',
370         marcorgcode      => 'marc_org_code',
371         opacusercss      => undef,
372         opacuserjs       => undef
373     };
374 }
375
376 =head3 opac_info
377
378     $library->opac_info({ lang => $lang });
379
380 Returns additional contents block OpacLibraryInfo for $lang or 'default'.
381
382 Note: This replaces the former branches.opac_info column.
383
384 =cut
385
386 sub opac_info {
387     my ( $self, $params ) = @_;
388     return Koha::AdditionalContents->find_best_match({
389         category => 'html_customizations',
390         location => 'OpacLibraryInfo',
391         lang => $params->{lang},
392         library_id => $self->branchcode,
393     });
394 }
395
396
397 =head3 get_float_libraries
398
399 Return all libraries belonging to the same float group
400
401 =cut
402
403 sub get_float_libraries {
404     my ($self) = @_;
405
406     my $library_groups = $self->library_groups;
407     my @float_libraries;
408
409     while ( my $library_group = $library_groups->next ) {
410         my $root = Koha::Library::Groups->get_root_ancestor( { id => $library_group->id } );
411         if ( $root->ft_local_float_group ) {
412             push @float_libraries, $root->all_libraries;
413         }
414     }
415
416     my %seen;
417     @float_libraries =
418         grep { !$seen{ $_->id }++ } @float_libraries;
419
420     return Koha::Libraries->search( { branchcode => { '-in' => [ keys %seen ] } } );
421 }
422
423 =head3 validate_float_sibling
424
425 Return if given library is a valid float group member
426
427 =cut
428
429 sub validate_float_sibling {
430     my ( $self, $params ) = @_;
431
432     return 1 if $params->{branchcode} eq $self->id;
433
434     my $branchcode = $params->{branchcode};
435     return $self->get_float_libraries->search( { branchcode => $branchcode } )->count > 0;
436 }
437
438 =head3 library_hours
439
440 Returns the open and close times for a library.
441
442 =cut
443
444 sub library_hours {
445     my $self             = shift;
446     my $library_hours_rs = $self->_result->library_hours;
447     return Koha::Library::Hours->_new_from_dbic($library_hours_rs);
448 }
449
450 =head2 Internal methods
451
452 =head3 _type
453
454 =cut
455
456 sub _type {
457     return 'Branch';
458 }
459
460 1;