1 package Koha::Virtualshelf;
3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
25 use Koha::DateUtils qw( dt_from_string );
27 use Koha::Exceptions::Virtualshelf;
28 use Koha::Virtualshelfshare;
29 use Koha::Virtualshelfshares;
30 use Koha::Virtualshelfcontent;
31 use Koha::Virtualshelfcontents;
33 use base qw(Koha::Object);
37 Koha::Virtualshelf - Koha Virtualshelf Object class
48 unless ( $self->owner ) {
49 Koha::Exceptions::Virtualshelf::UseDbAdminAccount->throw;
52 unless ( $self->is_shelfname_valid ) {
53 Koha::Exceptions::Virtualshelf::DuplicateObject->throw;
56 $self->allow_change_from_owner( 1 )
57 unless defined $self->allow_change_from_owner;
58 $self->allow_change_from_others( 0 )
59 unless defined $self->allow_change_from_others;
60 $self->allow_change_from_staff( 0 )
61 unless defined $self->allow_change_from_staff;
63 $self->created_on( dt_from_string )
64 unless defined $self->created_on;
66 return $self->SUPER::store( $self );
76 return !$self->public;
79 sub is_shelfname_valid {
83 shelfname => $self->shelfname,
84 ( $self->shelfnumber ? ( "me.shelfnumber" => { '!=', $self->shelfnumber } ) : () ),
87 if ( $self->is_private and defined $self->owner ) {
88 $conditions->{-or} = {
89 "virtualshelfshares.borrowernumber" => $self->owner,
90 "me.owner" => $self->owner,
92 $conditions->{public} = 0;
94 elsif ( $self->is_private and not defined $self->owner ) {
95 $conditions->{owner} = undef;
96 $conditions->{public} = 0;
99 $conditions->{public} = 1;
102 my $count = Koha::Virtualshelves->search(
105 join => 'virtualshelfshares',
108 return $count ? 0 : 1;
113 my $rs = $self->_result->virtualshelfshares;
114 my $shares = Koha::Virtualshelfshares->_new_from_dbic( $rs );
120 my $rs = $self->_result->virtualshelfcontents;
121 my $contents = Koha::Virtualshelfcontents->_new_from_dbic( $rs );
126 my ( $self, $key ) = @_;
128 Koha::Exceptions::Virtualshelf::InvalidKeyOnSharing->throw;
130 Koha::Virtualshelfshare->new(
132 shelfnumber => $self->shelfnumber,
134 sharedate => dt_from_string,
141 return $self->get_shares->search(
143 borrowernumber => { '!=' => undef },
149 my ( $self, $borrowernumber ) = @_;
150 return unless $borrowernumber;
151 return $self->get_shares->search(
153 borrowernumber => $borrowernumber,
159 my ( $self, $borrowernumber ) = @_;
160 my $shelves = Koha::Virtualshelfshares->search(
162 shelfnumber => $self->shelfnumber,
163 borrowernumber => $borrowernumber,
166 return 0 unless $shelves->count;
168 # Only 1 share with 1 patron can exist
169 return $shelves->next->delete;
173 my ( $self, $biblionumber, $borrowernumber ) = @_;
174 return unless $biblionumber;
175 my $already_exists = $self->get_contents->search(
177 biblionumber => $biblionumber,
180 return if $already_exists;
183 my $patron = Koha::Patrons->find( $borrowernumber ) or return 0;
184 return 0 unless ( $self->owner == $borrowernumber && $self->allow_change_from_owner ) || ( $self->allow_change_from_staff && $patron->can_patron_change_staff_only_lists ) || $self->allow_change_from_others;
186 my $content = Koha::Virtualshelfcontent->new(
188 shelfnumber => $self->shelfnumber,
189 biblionumber => $biblionumber,
190 borrowernumber => $borrowernumber,
193 $self->lastmodified(dt_from_string);
200 my ( $self, $params ) = @_;
201 my $biblionumbers = $params->{biblionumbers} || [];
202 my $borrowernumber = $params->{borrowernumber};
203 return unless @$biblionumbers;
205 my $number_removed = 0;
206 my $patron = Koha::Patrons->find( $borrowernumber ) or return 0;
207 if( ( $self->owner == $borrowernumber && $self->allow_change_from_owner )
208 || ( $self->allow_change_from_staff && $patron->can_patron_change_staff_only_lists )
209 || $self->allow_change_from_others ) {
210 $number_removed += $self->get_contents->search({
211 biblionumber => $biblionumbers,
214 return $number_removed;
218 my ( $self, $borrowernumber ) = @_;
219 return 1 if $self->is_public;
220 return 0 unless $borrowernumber;
221 return 1 if $self->owner == $borrowernumber;
222 return $self->get_shares->search(
224 borrowernumber => $borrowernumber,
230 my ( $self, $borrowernumber ) = @_;
232 return 0 unless $borrowernumber;
233 return 1 if $self->owner == $borrowernumber;
235 my $patron = Koha::Patrons->find( $borrowernumber ) or return 0;
237 return 1 if $self->is_public and C4::Auth::haspermission( $patron->userid, { lists => 'delete_public_lists' } );
243 my ( $self, $borrowernumber ) = @_;
245 if $borrowernumber and $self->owner == $borrowernumber;
247 my $patron = Koha::Patrons->find( $borrowernumber ) or return 0;
249 if $self->is_public and C4::Auth::haspermission( $patron->userid, { lists => 'edit_public_lists' } );
253 sub can_biblios_be_added {
254 my ( $self, $borrowernumber ) = @_;
256 my $patron = Koha::Patrons->find( $borrowernumber ) or return 0;
259 and ( ( $self->owner == $borrowernumber && $self->allow_change_from_owner ) or ( $self->allow_change_from_staff && $patron->can_patron_change_staff_only_lists ) or $self->allow_change_from_others );
263 sub can_biblios_be_removed {
264 my ( $self, $borrowernumber ) = @_;
265 return $self->can_biblios_be_added( $borrowernumber );
266 # Same answer since bug 18228
269 =head3 cannot_be_transferred
271 $shelf->cannot_be_transferred({
272 by => $p1, to => $p2, interface => opac|intranet|undef,
273 # p1 and p2 are borrowernumbers
276 This routine has two main goals:
277 [1] Decide if patron may transfer a shared list to another
279 [2] Decide if staff member may transfer a public list.
281 If you pass interface, we'll check if it supports transfer too.
282 NOTE: The explicit passing is still more reliable than via context,
283 since we could switch interface after login in the same session.
285 Returns a true value (read: error_code) when not allowed.
286 The following error codes are possible:
287 unauthorized_transfer, missing_by_parameter, new_owner_not_found,
288 new_owner_has_no_share, missing_to_parameter.
289 Otherwise returns false (zero).
293 sub cannot_be_transferred {
294 my ( $self, $params ) = @_;
295 my $to = $params->{to};
296 my $by = $params->{by};
297 my $interface = $params->{interface};
299 # Check on interface: currently we don't support transfer shared on intranet, transfer public on OPAC
301 return 'unauthorized_transfer'
302 if ( $self->public && $interface eq 'opac' ) or
303 ( $self->is_private && $interface eq 'intranet' );
304 # is_private call is enough here, get_shares tested below
307 my $shares = $self->public ? undef : $self->get_shares->search({ borrowernumber => { '!=' => undef } });
308 return 'unauthorized_transfer' if $self->is_private && !$shares->count;
311 if( $self->public ) {
312 my $by_patron = Koha::Patrons->find($by);
313 return 'unauthorized_transfer'
314 if !$by_patron || !C4::Auth::haspermission( $by_patron->userid, { lists => 'edit_public_lists' });
316 return 'unauthorized_transfer' if !$self->can_be_managed($by);
319 return 'missing_by_parameter';
323 if( !Koha::Patrons->find($to) ) {
324 return 'new_owner_not_found';
326 if( !$self->public && !$shares->search({ borrowernumber => $to })->count ) {
327 return 'new_owner_has_no_share';
330 return 'missing_to_parameter';
332 return 0; # serving as green light
335 =head3 transfer_ownership
337 $list->transfer_ownership( $patron_id );
339 This method transfers the list ownership to the passed I<$patron_id>.
343 sub transfer_ownership {
344 my ( $self, $patron_id ) = @_;
346 Koha::Exceptions::MissingParameter->throw( "Mandatory parameter 'patron' missing" )
349 $self->remove_share( $patron_id ) if $self->is_private;
350 return $self->set({ owner => $patron_id })->store;
353 =head2 Internal methods
360 return 'Virtualshelve';