1 package C4::VirtualShelves;
3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
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
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.
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.
27 use constant SHELVES_MASTHEAD_MAX => 10; #number under Lists button in masthead
28 use constant SHELVES_COMBO_MAX => 10; #add to combo in search
29 use constant SHELVES_MGRPAGE_MAX => 20; #managing page
30 use constant SHELVES_POPUP_MAX => 40; #addbybiblio popup
32 use constant SHARE_INVITATION_EXPIRY_DAYS => 14; #two weeks to accept
34 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
37 # set the version for version checking
38 $VERSION = 3.07.00.049;
42 &GetShelves &GetShelfContents &GetShelf
46 &DelFromShelf &DelShelf
48 &AddShare &AcceptShare &RemoveShare &IsSharedList
51 &GetAllShelves &ShelvesMax
58 C4::VirtualShelves - Functions for manipulating Koha virtual shelves
62 use C4::VirtualShelves;
66 This module provides functions for manipulating virtual shelves,
67 including creating and deleting virtual shelves, and adding and removing
68 bibs to and from virtual shelves.
74 $shelflist = &GetShelves($category, $row_count, $offset, $owner);
75 ($shelfnumber, $shelfhash) = each %{$shelflist};
77 Returns the number of shelves specified by C<$row_count> and C<$offset> as well as the total
78 number of shelves that meet the C<$owner> and C<$category> criteria. C<$category>,
79 C<$row_count>, and C<$offset> are required. C<$owner> must be supplied when C<$category> == 1.
80 When C<$category> is 2, supply undef as argument for C<$owner>.
82 This function is used by shelfpage in VirtualShelves/Page.pm when listing all shelves for lists management in opac or staff client. Order is by shelfname.
84 C<$shelflist>is a reference-to-hash. The keys are the virtualshelves numbers (C<$shelfnumber>, above),
85 and the values (C<$shelfhash>, above) are themselves references-to-hash, with the following keys:
89 =item C<$shelfhash-E<gt>{shelfname}>
91 A string. The name of the shelf.
98 my ($category, $row_count, $offset, $owner) = @_;
100 my @params = ( $offset, $row_count );
101 my $dbh = C4::Context->dbh;
103 SELECT vs.shelfnumber, vs.shelfname,vs.owner,
104 bo.surname,bo.firstname,vs.category,vs.sortfield,
105 count(vc.biblionumber) as count
106 FROM virtualshelves vs
107 LEFT JOIN borrowers bo ON vs.owner=bo.borrowernumber
108 LEFT JOIN virtualshelfcontents vc USING (shelfnumber) };
111 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
112 AND sh.borrowernumber=?
113 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
114 unshift @params, ($owner) x 3;
117 $query.= 'WHERE category=2 ';
120 GROUP BY vs.shelfnumber
121 ORDER BY vs.shelfname
124 my $sth2 = $dbh->prepare($query);
125 $sth2->execute(@params);
127 while( my ($shelfnumber, $shelfname, $owner, $surname, $firstname, $category, $sortfield, $count)= $sth2->fetchrow) {
128 $shelflist{$shelfnumber}->{'shelfname'} = $shelfname;
129 $shelflist{$shelfnumber}->{'count'} = $count;
130 $shelflist{$shelfnumber}->{'single'} = $count==1;
131 $shelflist{$shelfnumber}->{'sortfield'} = $sortfield;
132 $shelflist{$shelfnumber}->{'category'} = $category;
133 $shelflist{$shelfnumber}->{'owner'} = $owner;
134 $shelflist{$shelfnumber}->{'surname'} = $surname;
135 $shelflist{$shelfnumber}->{'firstname'} = $firstname;
142 $shelflist = GetAllShelves($category, $owner)
144 This function returns a reference to an array of hashrefs containing all shelves
145 sorted by the shelf name.
147 This function is intended to return a dataset reflecting all the shelves for
148 the submitted parameters.
153 my ($category,$owner,$adding_allowed) = @_;
155 my $dbh = C4::Context->dbh;
156 my $query = 'SELECT vs.* FROM virtualshelves vs ';
159 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
160 AND sh.borrowernumber=?
161 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
162 @params = ($owner, $owner, $owner);
165 $query.='WHERE category=2 ';
168 $query.='AND (allow_add=1 OR owner=?) ' if $adding_allowed;
169 push @params, $owner if $adding_allowed;
170 $query.= 'ORDER BY shelfname ASC';
171 my $sth = $dbh->prepare( $query );
172 $sth->execute(@params);
173 return $sth->fetchall_arrayref({});
176 =head2 GetSomeShelfNames
178 Returns shelf names and numbers for Add to combo of search results and Lists button of OPAC header.
182 sub GetSomeShelfNames {
183 my ($owner, $purpose, $adding_allowed)= @_;
184 my ($bar, $pub, @params);
185 my $dbh = C4::Context->dbh;
187 my $bquery = 'SELECT vs.shelfnumber, vs.shelfname FROM virtualshelves vs ';
188 my $limit= ShelvesMax($purpose);
190 my $qry1= $bquery."WHERE vs.category=2 ";
191 $qry1.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
192 push @params, $owner||0 if $adding_allowed;
193 $qry1.= "ORDER BY vs.lastmodified DESC LIMIT $limit";
195 unless($adding_allowed && (!defined($owner) || $owner<=0)) {
196 #if adding items, user should be known
197 $pub= $dbh->selectall_arrayref($qry1,{Slice=>{}},@params);
201 my $qry2= $bquery. qq{
202 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber AND sh.borrowernumber=?
203 WHERE vs.category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
204 @params=($owner,$owner,$owner);
205 $qry2.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
206 push @params, $owner if $adding_allowed;
207 $qry2.= "ORDER BY vs.lastmodified DESC ";
208 $qry2.= "LIMIT $limit";
209 $bar= $dbh->selectall_arrayref($qry2,{Slice=>{}},@params);
212 return ( { bartotal => $bar? scalar @$bar: 0, pubtotal => $pub? scalar @$pub: 0}, $pub, $bar);
217 (shelfnumber,shelfname,owner,category,sortfield,allow_add,allow_delete_own,allow_delete_other) = &GetShelf($shelfnumber);
219 Returns the above-mentioned fields for passed virtual shelf number.
224 my ($shelfnumber) = @_;
225 my $dbh = C4::Context->dbh;
227 SELECT shelfnumber, shelfname, owner, category, sortfield,
228 allow_add, allow_delete_own, allow_delete_other
232 my $sth = $dbh->prepare($query);
233 $sth->execute($shelfnumber);
234 return $sth->fetchrow;
237 =head2 GetShelfContents
239 $biblist = &GetShelfContents($shelfnumber);
241 Looks up information about the contents of virtual virtualshelves number
242 C<$shelfnumber>. Sorted by a field in the biblio table. copyrightdate
245 Returns a reference-to-array, whose elements are references-to-hash,
246 as returned by C<C4::Biblio::GetBiblioFromItemNumber>.
248 Note: the notforloan status comes from the itemtype, and where it equals 0
249 it does not ensure that related items.notforloan status is likewise 0. The
250 caller has to check any items on their own, possibly with CanBookBeIssued
251 from C4::Circulation.
255 sub GetShelfContents {
256 my ($shelfnumber, $row_count, $offset, $sortfield, $sort_direction ) = @_;
257 my $dbh=C4::Context->dbh();
258 my $sth1 = $dbh->prepare("SELECT count(*) FROM virtualshelfcontents WHERE shelfnumber = ?");
259 $sth1->execute($shelfnumber);
260 my $total = $sth1->fetchrow;
262 my $sth2 = $dbh->prepare('SELECT sortfield FROM virtualshelves WHERE shelfnumber=?');
263 $sth2->execute($shelfnumber);
264 ($sortfield) = $sth2->fetchrow_array;
267 " SELECT DISTINCT vc.biblionumber, vc.shelfnumber, vc.dateadded, itemtypes.*,
268 biblio.*, biblioitems.itemtype, biblioitems.publicationyear as year, biblioitems.publishercode, biblioitems.place, biblioitems.size, biblioitems.pages
269 FROM virtualshelfcontents vc
270 JOIN biblio ON vc.biblionumber = biblio.biblionumber
271 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
272 LEFT JOIN items ON items.biblionumber=vc.biblionumber
273 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
274 WHERE vc.shelfnumber=? ";
275 my @params = ($shelfnumber);
277 $query .= " ORDER BY " . $dbh->quote_identifier( $sortfield );
278 $query .= " DESC " if ( $sort_direction eq 'desc' );
281 $query .= " LIMIT ?, ? ";
282 push (@params, ($offset ? $offset : 0));
283 push (@params, $row_count);
285 my $sth3 = $dbh->prepare($query);
286 $sth3->execute(@params);
287 return ($sth3->fetchall_arrayref({}), $total);
288 # Like the perldoc says,
289 # returns reference-to-array, where each element is reference-to-hash of the row:
290 # like [ $sth->fetchrow_hashref(), $sth->fetchrow_hashref() ... ]
291 # Suitable for use in TMPL_LOOP.
292 # See http://search.cpan.org/~timb/DBI-1.601/DBI.pm#fetchall_arrayref
293 # or newer, for your version of DBI.
298 $shelfnumber = &AddShelf($hashref, $owner);
300 Creates a new virtual shelf. Params passed in a hash like ModShelf.
302 Returns a code to know what's happen.
303 * -1 : if this virtualshelves already exists.
304 * $shelfnumber : if success.
309 my ($hashref, $owner)= @_;
310 my $dbh = C4::Context->dbh;
312 #initialize missing hash values to silence warnings
313 foreach('shelfname','category', 'sortfield', 'allow_add', 'allow_delete_own', 'allow_delete_other' ) {
314 $hashref->{$_}= undef unless exists $hashref->{$_};
317 return -1 unless _CheckShelfName($hashref->{shelfname}, $hashref->{category}, $owner, 0);
319 my $query = qq(INSERT INTO virtualshelves
320 (shelfname,owner,category,sortfield,allow_add,allow_delete_own,allow_delete_other)
321 VALUES (?,?,?,?,?,?,?));
323 my $sth = $dbh->prepare($query);
325 $hashref->{shelfname},
327 $hashref->{category},
328 $hashref->{sortfield},
329 $hashref->{allow_add}//0,
330 $hashref->{allow_delete_own}//1,
331 $hashref->{allow_delete_other}//0 );
333 my $shelfnumber = $dbh->{'mysql_insertid'};
339 &AddToShelf($biblionumber, $shelfnumber, $borrower);
341 Adds bib number C<$biblionumber> to virtual virtualshelves number
342 C<$shelfnumber>, unless that bib is already on that shelf.
347 my ($biblionumber, $shelfnumber, $borrowernumber) = @_;
348 return unless $biblionumber;
349 my $dbh = C4::Context->dbh;
352 FROM virtualshelfcontents
353 WHERE shelfnumber=? AND biblionumber=?
355 my $sth = $dbh->prepare($query);
357 $sth->execute( $shelfnumber, $biblionumber );
358 ($sth->rows) and return; # already on shelf
360 INSERT INTO virtualshelfcontents
361 (shelfnumber, biblionumber, flags, borrowernumber)
362 VALUES (?, ?, 0, ?));
363 $sth = $dbh->prepare($query);
364 $sth->execute( $shelfnumber, $biblionumber, $borrowernumber);
365 $query = qq(UPDATE virtualshelves
366 SET lastmodified = CURRENT_TIMESTAMP
367 WHERE shelfnumber = ?);
368 $sth = $dbh->prepare($query);
369 $sth->execute( $shelfnumber );
374 my $result= ModShelf($shelfnumber, $hashref)
376 Where $hashref->{column} = param
378 Modify the value into virtualshelves table with values given
379 from hashref, which each key of the hashref should be
380 the name of a column of virtualshelves.
381 Fields like shelfnumber or owner cannot be changed.
383 Returns 1 if the action seemed to be successful.
388 my ($shelfnumber,$hashref) = @_;
389 my $dbh = C4::Context->dbh;
391 my $query= "SELECT * FROM virtualshelves WHERE shelfnumber=?";
392 my $sth = $dbh->prepare($query);
393 $sth->execute($shelfnumber);
394 my $oldrecord= $sth->fetchrow_hashref;
395 return 0 unless $oldrecord; #not found?
397 #initialize missing hash values to silence warnings
398 foreach('shelfname','category', 'sortfield', 'allow_add', 'allow_delete_own', 'allow_delete_other' ) {
399 $hashref->{$_}= undef unless exists $hashref->{$_};
402 #if name or category changes, the name should be tested
403 if($hashref->{shelfname} || $hashref->{category}) {
404 unless(_CheckShelfName(
405 $hashref->{shelfname}//$oldrecord->{shelfname},
406 $hashref->{category}//$oldrecord->{category},
409 return 0; #name check failed
413 #only the following fields from the hash may be changed
414 $query= "UPDATE virtualshelves SET shelfname=?, category=?, sortfield=?, allow_add=?, allow_delete_own=?, allow_delete_other=? WHERE shelfnumber=?";
415 $sth = $dbh->prepare($query);
417 $hashref->{shelfname}//$oldrecord->{shelfname},
418 $hashref->{category}//$oldrecord->{category},
419 $hashref->{sortfield}//$oldrecord->{sortfield},
420 $hashref->{allow_add}//$oldrecord->{allow_add},
421 $hashref->{allow_delete_own}//$oldrecord->{allow_delete_own},
422 $hashref->{allow_delete_other}//$oldrecord->{allow_delete_other},
427 =head2 ShelfPossibleAction
429 ShelfPossibleAction($loggedinuser, $shelfnumber, $action);
431 C<$loggedinuser,$shelfnumber,$action>
433 $action can be "view", "add", "delete", "manage", "new_public", "new_private".
434 New additional actions are: invite, acceptshare.
435 Note that add/delete here refers to adding/deleting entries from the list. Deleting the list itself falls under manage.
436 new_public and new_private refers to creating a new public or private list.
437 The distinction between deleting your own entries from the list or entries from
438 others is made in DelFromShelf.
440 Returns 1 if the user can do the $action in the $shelfnumber shelf.
442 For the actions invite and acceptshare a second errorcode is returned if the
443 result is false. See opac-shareshelf.pl
447 sub ShelfPossibleAction {
448 my ( $user, $shelfnumber, $action ) = @_;
449 $action= 'view' unless $action;
450 $user=0 unless $user;
452 if($action =~ /^new/) { #no shelfnumber needed
453 if($action eq 'new_private') {
456 elsif($action eq 'new_public') {
457 return $user>0 && C4::Context->preference('OpacAllowPublicListCreation');
462 return 0 unless defined($shelfnumber);
464 my $dbh = C4::Context->dbh;
466 SELECT COALESCE(owner,0) AS owner, category, allow_add, allow_delete_own, allow_delete_other, COALESCE(sh.borrowernumber,0) AS borrowernumber
467 FROM virtualshelves vs
468 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
469 AND sh.borrowernumber=?
470 WHERE vs.shelfnumber=?
472 my $sth = $dbh->prepare($query);
473 $sth->execute($user, $shelfnumber);
474 my $shelf= $sth->fetchrow_hashref;
476 return 0 unless $shelf && ($shelf->{category}==2 || $shelf->{owner}==$user || ($user && $shelf->{borrowernumber}==$user));
477 if($action eq 'view') {
478 #already handled in the above condition
481 elsif($action eq 'add') {
482 return 0 if $user<=0; #should be logged in
483 return 1 if $shelf->{allow_add}==1 || $shelf->{owner}==$user;
484 #owner may always add
486 elsif($action eq 'delete') {
487 #this answer is just diplomatic: it says that you may be able to delete
488 #some items from that shelf
489 #it does not answer the question about a specific biblio
490 #DelFromShelf checks the situation per biblio
491 return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
493 elsif($action eq 'invite') {
494 #for sharing you must be the owner and the list must be private
495 if( $shelf->{category}==1 ) {
496 return 1 if $shelf->{owner}==$user;
497 return (0, 4); # code 4: should be owner
500 return (0, 5); # code 5: should be private list
503 elsif($action eq 'acceptshare') {
504 #the key for accepting is checked later in AcceptShare
505 #you must not be the owner, list must be private
506 if( $shelf->{category}==1 ) {
507 return (0, 8) if $shelf->{owner}==$user;
508 #code 8: should not be owner
512 return (0, 5); # code 5: should be private list
515 elsif($action eq 'manage') {
516 return 1 if $user && $shelf->{owner}==$user;
523 $result= &DelFromShelf( $bibref, $shelfnumber, $user);
525 Removes biblionumbers in passed arrayref from shelf C<$shelfnumber>.
526 If the bib wasn't on that virtualshelves to begin with, nothing happens.
528 Returns 0 if no items have been deleted.
533 my ($bibref, $shelfnumber, $user) = @_;
534 my $dbh = C4::Context->dbh;
535 my $query = qq(SELECT allow_delete_own, allow_delete_other FROM virtualshelves WHERE shelfnumber=?);
536 my $sth= $dbh->prepare($query);
537 $sth->execute($shelfnumber);
538 my ($del_own, $del_oth)= $sth->fetchrow;
542 $query = qq(DELETE FROM virtualshelfcontents
543 WHERE shelfnumber=? AND biblionumber=? AND borrowernumber=?);
544 $sth= $dbh->prepare($query);
545 foreach my $biblionumber (@$bibref) {
546 $sth->execute($shelfnumber, $biblionumber, $user);
547 $r= $sth->rows; #Expect -1, 0 or 1 (-1 means Don't know; count as 1)
548 $t+= ($r==-1)? 1: $r;
552 #includes a check if borrowernumber is null (deleted patron)
553 $query = qq/DELETE FROM virtualshelfcontents
554 WHERE shelfnumber=? AND biblionumber=? AND
555 (borrowernumber IS NULL OR borrowernumber<>?)/;
556 $sth= $dbh->prepare($query);
557 foreach my $biblionumber (@$bibref) {
558 $sth->execute($shelfnumber, $biblionumber, $user);
560 $t+= ($r==-1)? 1: $r;
568 $Number = DelShelf($shelfnumber);
570 This function deletes the shelf number, and all of it's content.
571 Authorization to do so MUST have been checked before calling, while using
572 ShelfPossibleAction with manage parameter.
577 my ($shelfnumber)= @_;
578 return unless $shelfnumber && $shelfnumber =~ /^\d+$/;
579 my $dbh = C4::Context->dbh;
580 my $sth = $dbh->prepare("DELETE FROM virtualshelves WHERE shelfnumber=?");
581 return $sth->execute($shelfnumber);
584 =head2 GetBibliosShelves
586 This finds all the public lists that this bib record is in.
590 sub GetBibliosShelves {
591 my ( $biblionumber ) = @_;
592 my $dbh = C4::Context->dbh;
593 my $sth = $dbh->prepare('
594 SELECT vs.shelfname, vs.shelfnumber
595 FROM virtualshelves vs
596 JOIN virtualshelfcontents vc ON (vs.shelfnumber= vc.shelfnumber)
598 AND vc.biblionumber= ?
600 $sth->execute( $biblionumber );
601 return $sth->fetchall_arrayref({});
606 $howmany= ShelvesMax($context);
608 Tells how much shelves are shown in which context.
609 POPUP refers to addbybiblionumber popup, MGRPAGE is managing page (in opac or
610 staff), COMBO refers to the Add to-combo of search results. MASTHEAD is the
611 main Koha toolbar with Lists button.
617 return SHELVES_POPUP_MAX if $which eq 'POPUP';
618 return SHELVES_MGRPAGE_MAX if $which eq 'MGRPAGE';
619 return SHELVES_COMBO_MAX if $which eq 'COMBO';
620 return SHELVES_MASTHEAD_MAX if $which eq 'MASTHEAD';
621 return SHELVES_MASTHEAD_MAX;
624 =head2 HandleDelBorrower
626 HandleDelBorrower($borrower);
628 When a member is deleted (DelMember in Members.pm), you should call me first.
629 This routine deletes/moves lists and entries for the deleted member/borrower.
630 Lists owned by the borrower are deleted, but entries from the borrower to
631 other lists are kept.
635 sub HandleDelBorrower {
638 my $dbh = C4::Context->dbh;
640 #Delete all lists and all shares of this borrower
641 #Consistent with the approach Koha uses on deleting individual lists
642 #Note that entries in virtualshelfcontents added by this borrower to
643 #lists of others will be handled by a table constraint: the borrower
644 #is set to NULL in those entries.
645 $query="DELETE FROM virtualshelves WHERE owner=?";
646 $dbh->do($query,undef,($borrower));
649 #We could handle the above deletes via a constraint too.
650 #But a new BZ report 11889 has been opened to discuss another approach.
651 #Instead of deleting we could also disown lists (based on a pref).
652 #In that way we could save shared and public lists.
653 #The current table constraints support that idea now.
654 #This pref should then govern the results of other routines such as
660 AddShare($shelfnumber, $key);
662 Adds a share request to the virtualshelves table.
663 Authorization must have been checked, and a key must be supplied. See script
664 opac-shareshelf.pl for an example.
665 This request is not yet confirmed. So it has no borrowernumber, it does have an
671 my ($shelfnumber, $key)= @_;
672 return if !$shelfnumber || !$key;
674 my $dbh = C4::Context->dbh;
675 my $sql = "INSERT INTO virtualshelfshares (shelfnumber, invitekey, sharedate) VALUES (?, ?, NOW())";
676 $dbh->do($sql, undef, ($shelfnumber, $key));
682 my $result= AcceptShare($shelfnumber, $key, $borrowernumber);
684 Checks acceptation of a share request.
685 Key must be found for this shelf. Invitation must not have expired.
686 Returns true when accepted, false otherwise.
691 my ($shelfnumber, $key, $borrowernumber)= @_;
692 return if !$shelfnumber || !$key || !$borrowernumber;
695 my $dbh = C4::Context->dbh;
697 UPDATE virtualshelfshares
698 SET invitekey=NULL, sharedate=NOW(), borrowernumber=?
699 WHERE shelfnumber=? AND invitekey=? AND (sharedate + INTERVAL ? DAY) >NOW()
701 my $i= $dbh->do($sql, undef, ($borrowernumber, $shelfnumber, $key, SHARE_INVITATION_EXPIRY_DAYS));
702 return if !defined($i) || !$i || $i eq '0E0'; #not found
708 my $bool= IsSharedList( $shelfnumber );
710 IsSharedList checks if a (private) list has shares.
711 Note that such a check would not be useful for public lists. A public list has
712 no shares, but is visible for anyone by nature..
713 Used to determine the list type in the display of Your lists (all private).
714 Returns boolean value.
719 my ($shelfnumber) = @_;
720 my $dbh = C4::Context->dbh;
721 my $sql="SELECT id FROM virtualshelfshares WHERE shelfnumber=? AND borrowernumber IS NOT NULL";
722 my $sth = $dbh->prepare($sql);
723 $sth->execute($shelfnumber);
724 my ($rv)= $sth->fetchrow_array;
730 RemoveShare( $user, $shelfnumber );
732 RemoveShare removes a share for specific shelf and borrower.
733 Returns true if a record could be deleted.
738 my ($user, $shelfnumber)= @_;
739 my $dbh = C4::Context->dbh;
741 DELETE FROM virtualshelfshares
742 WHERE borrowernumber=? AND shelfnumber=?
744 my $n= $dbh->do($sql,undef,($user, $shelfnumber));
745 return if !defined($n) || !$n || $n eq '0E0'; #nothing removed
751 my ($owner, $category) = @_;
753 # Find out how many shelves total meet the submitted criteria...
755 my $dbh = C4::Context->dbh;
756 my $query = "SELECT count(*) FROM virtualshelves vs ";
759 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
760 AND sh.borrowernumber=?
761 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
762 @params= ($owner, $owner, $owner);
765 $query.='WHERE category=2';
768 my $sth = $dbh->prepare($query);
769 $sth->execute(@params);
770 my ($total)= $sth->fetchrow;
775 sub _CheckShelfName {
776 my ($name, $cat, $owner, $number)= @_;
778 my $dbh = C4::Context->dbh;
781 SELECT DISTINCT shelfnumber
783 LEFT JOIN virtualshelfshares sh USING (shelfnumber)
784 WHERE shelfname=? AND shelfnumber<>?);
785 if($cat==1 && defined($owner)) {
786 $query.= ' AND (sh.borrowernumber=? OR owner=?) AND category=1';
787 @pars=($name, $number, $owner, $owner);
789 elsif($cat==1 && !defined($owner)) { #owner is null (exceptional)
790 $query.= ' AND owner IS NULL AND category=1';
791 @pars=($name, $number);
794 $query.= ' AND category=2';
795 @pars=($name, $number);
797 my $sth = $dbh->prepare($query);
798 $sth->execute(@pars);
799 return $sth->rows>0? 0: 1;
808 Koha Development Team <http://koha-community.org/>
812 C4::Circulation::Circ2(3)