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, $totshelves) = &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.
93 =item C<$shelfhash-E<gt>{count}>
95 The number of virtuals on that virtualshelves.
102 my ($category, $row_count, $offset, $owner) = @_;
104 my $total = _shelf_count($owner, $category);
105 my $dbh = C4::Context->dbh;
107 SELECT vs.shelfnumber, vs.shelfname,vs.owner,
108 bo.surname,bo.firstname,vs.category,vs.sortfield,
109 count(vc.biblionumber) as count
110 FROM virtualshelves vs
111 LEFT JOIN borrowers bo ON vs.owner=bo.borrowernumber
112 LEFT JOIN virtualshelfcontents vc USING (shelfnumber) };
115 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
116 AND sh.borrowernumber=?
117 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
118 @params= ($owner, $owner, $owner, $offset||0, $row_count);
121 $query.= 'WHERE category=2 ';
122 @params= ($offset||0, $row_count);
125 GROUP BY vs.shelfnumber
126 ORDER BY vs.shelfname
129 my $sth2 = $dbh->prepare($query);
130 $sth2->execute(@params);
132 while( my ($shelfnumber, $shelfname, $owner, $surname, $firstname, $category, $sortfield, $count)= $sth2->fetchrow) {
133 $shelflist{$shelfnumber}->{'shelfname'} = $shelfname;
134 $shelflist{$shelfnumber}->{'count'} = $count;
135 $shelflist{$shelfnumber}->{'single'} = $count==1;
136 $shelflist{$shelfnumber}->{'sortfield'} = $sortfield;
137 $shelflist{$shelfnumber}->{'category'} = $category;
138 $shelflist{$shelfnumber}->{'owner'} = $owner;
139 $shelflist{$shelfnumber}->{'surname'} = $surname;
140 $shelflist{$shelfnumber}->{'firstname'} = $firstname;
142 return ( \%shelflist, $total );
147 $shelflist = GetAllShelves($category, $owner)
149 This function returns a reference to an array of hashrefs containing all shelves
150 sorted by the shelf name.
152 This function is intended to return a dataset reflecting all the shelves for
153 the submitted parameters.
158 my ($category,$owner,$adding_allowed) = @_;
160 my $dbh = C4::Context->dbh;
161 my $query = 'SELECT vs.* FROM virtualshelves vs ';
164 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
165 AND sh.borrowernumber=?
166 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
167 @params = ($owner, $owner, $owner);
170 $query.='WHERE category=2 ';
173 $query.='AND (allow_add=1 OR owner=?) ' if $adding_allowed;
174 push @params, $owner if $adding_allowed;
175 $query.= 'ORDER BY shelfname ASC';
176 my $sth = $dbh->prepare( $query );
177 $sth->execute(@params);
178 return $sth->fetchall_arrayref({});
181 =head2 GetSomeShelfNames
183 Returns shelf names and numbers for Add to combo of search results and Lists button of OPAC header.
187 sub GetSomeShelfNames {
188 my ($owner, $purpose, $adding_allowed)= @_;
189 my ($bar, $pub, @params);
190 my $dbh = C4::Context->dbh;
192 my $bquery = 'SELECT vs.shelfnumber, vs.shelfname FROM virtualshelves vs ';
193 my $limit= ShelvesMax($purpose);
195 my $qry1= $bquery."WHERE vs.category=2 ";
196 $qry1.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
197 push @params, $owner||0 if $adding_allowed;
198 $qry1.= "ORDER BY vs.lastmodified DESC LIMIT $limit";
200 unless($adding_allowed && (!defined($owner) || $owner<=0)) {
201 #if adding items, user should be known
202 $pub= $dbh->selectall_arrayref($qry1,{Slice=>{}},@params);
206 my $qry2= $bquery. qq{
207 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber AND sh.borrowernumber=?
208 WHERE vs.category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
209 @params=($owner,$owner,$owner);
210 $qry2.= "AND (allow_add=1 OR owner=?) " if $adding_allowed;
211 push @params, $owner if $adding_allowed;
212 $qry2.= "ORDER BY vs.lastmodified DESC ";
213 $qry2.= "LIMIT $limit";
214 $bar= $dbh->selectall_arrayref($qry2,{Slice=>{}},@params);
217 return ( { bartotal => $bar? scalar @$bar: 0, pubtotal => $pub? scalar @$pub: 0}, $pub, $bar);
222 (shelfnumber,shelfname,owner,category,sortfield,allow_add,allow_delete_own,allow_delete_other) = &GetShelf($shelfnumber);
224 Returns the above-mentioned fields for passed virtual shelf number.
229 my ($shelfnumber) = @_;
230 my $dbh = C4::Context->dbh;
232 SELECT shelfnumber, shelfname, owner, category, sortfield,
233 allow_add, allow_delete_own, allow_delete_other
237 my $sth = $dbh->prepare($query);
238 $sth->execute($shelfnumber);
239 return $sth->fetchrow;
242 =head2 GetShelfContents
244 $biblist = &GetShelfContents($shelfnumber);
246 Looks up information about the contents of virtual virtualshelves number
247 C<$shelfnumber>. Sorted by a field in the biblio table. copyrightdate
250 Returns a reference-to-array, whose elements are references-to-hash,
251 as returned by C<C4::Biblio::GetBiblioFromItemNumber>.
253 Note: the notforloan status comes from the itemtype, and where it equals 0
254 it does not ensure that related items.notforloan status is likewise 0. The
255 caller has to check any items on their own, possibly with CanBookBeIssued
256 from C4::Circulation.
260 sub GetShelfContents {
261 my ($shelfnumber, $row_count, $offset, $sortfield, $sort_direction ) = @_;
262 my $dbh=C4::Context->dbh();
263 my $sth1 = $dbh->prepare("SELECT count(*) FROM virtualshelfcontents WHERE shelfnumber = ?");
264 $sth1->execute($shelfnumber);
265 my $total = $sth1->fetchrow;
267 my $sth2 = $dbh->prepare('SELECT sortfield FROM virtualshelves WHERE shelfnumber=?');
268 $sth2->execute($shelfnumber);
269 ($sortfield) = $sth2->fetchrow_array;
272 " SELECT DISTINCT vc.biblionumber, vc.shelfnumber, vc.dateadded, itemtypes.*,
273 biblio.*, biblioitems.itemtype, biblioitems.publicationyear as year, biblioitems.publishercode, biblioitems.place, biblioitems.size, biblioitems.pages
274 FROM virtualshelfcontents vc
275 JOIN biblio ON vc.biblionumber = biblio.biblionumber
276 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
277 LEFT JOIN items ON items.biblionumber=vc.biblionumber
278 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
279 WHERE vc.shelfnumber=? ";
280 my @params = ($shelfnumber);
282 $query .= " ORDER BY " . $dbh->quote_identifier( $sortfield );
283 $query .= " DESC " if ( $sort_direction eq 'desc' );
286 $query .= " LIMIT ?, ? ";
287 push (@params, ($offset ? $offset : 0));
288 push (@params, $row_count);
290 my $sth3 = $dbh->prepare($query);
291 $sth3->execute(@params);
292 return ($sth3->fetchall_arrayref({}), $total);
293 # Like the perldoc says,
294 # returns reference-to-array, where each element is reference-to-hash of the row:
295 # like [ $sth->fetchrow_hashref(), $sth->fetchrow_hashref() ... ]
296 # Suitable for use in TMPL_LOOP.
297 # See http://search.cpan.org/~timb/DBI-1.601/DBI.pm#fetchall_arrayref
298 # or newer, for your version of DBI.
303 $shelfnumber = &AddShelf($hashref, $owner);
305 Creates a new virtual shelf. Params passed in a hash like ModShelf.
307 Returns a code to know what's happen.
308 * -1 : if this virtualshelves already exists.
309 * $shelfnumber : if success.
314 my ($hashref, $owner)= @_;
315 my $dbh = C4::Context->dbh;
317 #initialize missing hash values to silence warnings
318 foreach('shelfname','category', 'sortfield', 'allow_add', 'allow_delete_own', 'allow_delete_other' ) {
319 $hashref->{$_}= undef unless exists $hashref->{$_};
322 return -1 unless _CheckShelfName($hashref->{shelfname}, $hashref->{category}, $owner, 0);
324 my $query = qq(INSERT INTO virtualshelves
325 (shelfname,owner,category,sortfield,allow_add,allow_delete_own,allow_delete_other)
326 VALUES (?,?,?,?,?,?,?));
328 my $sth = $dbh->prepare($query);
330 $hashref->{shelfname},
332 $hashref->{category},
333 $hashref->{sortfield},
334 $hashref->{allow_add}//0,
335 $hashref->{allow_delete_own}//1,
336 $hashref->{allow_delete_other}//0 );
337 my $shelfnumber = $dbh->{'mysql_insertid'};
343 &AddToShelf($biblionumber, $shelfnumber, $borrower);
345 Adds bib number C<$biblionumber> to virtual virtualshelves number
346 C<$shelfnumber>, unless that bib is already on that shelf.
351 my ($biblionumber, $shelfnumber, $borrowernumber) = @_;
352 return unless $biblionumber;
353 my $dbh = C4::Context->dbh;
356 FROM virtualshelfcontents
357 WHERE shelfnumber=? AND biblionumber=?
359 my $sth = $dbh->prepare($query);
361 $sth->execute( $shelfnumber, $biblionumber );
362 ($sth->rows) and return; # already on shelf
364 INSERT INTO virtualshelfcontents
365 (shelfnumber, biblionumber, flags, borrowernumber)
366 VALUES (?, ?, 0, ?));
367 $sth = $dbh->prepare($query);
368 $sth->execute( $shelfnumber, $biblionumber, $borrowernumber);
369 $query = qq(UPDATE virtualshelves
370 SET lastmodified = CURRENT_TIMESTAMP
371 WHERE shelfnumber = ?);
372 $sth = $dbh->prepare($query);
373 $sth->execute( $shelfnumber );
378 my $result= ModShelf($shelfnumber, $hashref)
380 Where $hashref->{column} = param
382 Modify the value into virtualshelves table with values given
383 from hashref, which each key of the hashref should be
384 the name of a column of virtualshelves.
385 Fields like shelfnumber or owner cannot be changed.
387 Returns 1 if the action seemed to be successful.
392 my ($shelfnumber,$hashref) = @_;
393 my $dbh = C4::Context->dbh;
395 my $query= "SELECT * FROM virtualshelves WHERE shelfnumber=?";
396 my $sth = $dbh->prepare($query);
397 $sth->execute($shelfnumber);
398 my $oldrecord= $sth->fetchrow_hashref;
399 return 0 unless $oldrecord; #not found?
401 #initialize missing hash values to silence warnings
402 foreach('shelfname','category', 'sortfield', 'allow_add', 'allow_delete_own', 'allow_delete_other' ) {
403 $hashref->{$_}= undef unless exists $hashref->{$_};
406 #if name or category changes, the name should be tested
407 if($hashref->{shelfname} || $hashref->{category}) {
408 unless(_CheckShelfName(
409 $hashref->{shelfname}//$oldrecord->{shelfname},
410 $hashref->{category}//$oldrecord->{category},
413 return 0; #name check failed
417 #only the following fields from the hash may be changed
418 $query= "UPDATE virtualshelves SET shelfname=?, category=?, sortfield=?, allow_add=?, allow_delete_own=?, allow_delete_other=? WHERE shelfnumber=?";
419 $sth = $dbh->prepare($query);
421 $hashref->{shelfname}//$oldrecord->{shelfname},
422 $hashref->{category}//$oldrecord->{category},
423 $hashref->{sortfield}//$oldrecord->{sortfield},
424 $hashref->{allow_add}//$oldrecord->{allow_add},
425 $hashref->{allow_delete_own}//$oldrecord->{allow_delete_own},
426 $hashref->{allow_delete_other}//$oldrecord->{allow_delete_other},
431 =head2 ShelfPossibleAction
433 ShelfPossibleAction($loggedinuser, $shelfnumber, $action);
435 C<$loggedinuser,$shelfnumber,$action>
437 $action can be "view", "add", "delete", "manage", "new_public", "new_private".
438 New additional actions are: invite, acceptshare.
439 Note that add/delete here refers to adding/deleting entries from the list. Deleting the list itself falls under manage.
440 new_public and new_private refers to creating a new public or private list.
441 The distinction between deleting your own entries from the list or entries from
442 others is made in DelFromShelf.
444 Returns 1 if the user can do the $action in the $shelfnumber shelf.
446 For the actions invite and acceptshare a second errorcode is returned if the
447 result is false. See opac-shareshelf.pl
451 sub ShelfPossibleAction {
452 my ( $user, $shelfnumber, $action ) = @_;
453 $action= 'view' unless $action;
454 $user=0 unless $user;
456 if($action =~ /^new/) { #no shelfnumber needed
457 if($action eq 'new_private') {
460 elsif($action eq 'new_public') {
461 return $user>0 && C4::Context->preference('OpacAllowPublicListCreation');
466 return 0 unless defined($shelfnumber);
468 my $dbh = C4::Context->dbh;
470 SELECT COALESCE(owner,0) AS owner, category, allow_add, allow_delete_own, allow_delete_other, COALESCE(sh.borrowernumber,0) AS borrowernumber
471 FROM virtualshelves vs
472 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
473 AND sh.borrowernumber=?
474 WHERE vs.shelfnumber=?
476 my $sth = $dbh->prepare($query);
477 $sth->execute($user, $shelfnumber);
478 my $shelf= $sth->fetchrow_hashref;
480 return 0 unless $shelf && ($shelf->{category}==2 || $shelf->{owner}==$user || ($user && $shelf->{borrowernumber}==$user));
481 if($action eq 'view') {
482 #already handled in the above condition
485 elsif($action eq 'add') {
486 return 0 if $user<=0; #should be logged in
487 return 1 if $shelf->{allow_add}==1 || $shelf->{owner}==$user;
488 #owner may always add
490 elsif($action eq 'delete') {
491 #this answer is just diplomatic: it says that you may be able to delete
492 #some items from that shelf
493 #it does not answer the question about a specific biblio
494 #DelFromShelf checks the situation per biblio
495 return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
497 elsif($action eq 'invite') {
498 #for sharing you must be the owner and the list must be private
499 if( $shelf->{category}==1 ) {
500 return 1 if $shelf->{owner}==$user;
501 return (0, 4); # code 4: should be owner
504 return (0, 5); # code 5: should be private list
507 elsif($action eq 'acceptshare') {
508 #the key for accepting is checked later in AcceptShare
509 #you must not be the owner, list must be private
510 if( $shelf->{category}==1 ) {
511 return (0, 8) if $shelf->{owner}==$user;
512 #code 8: should not be owner
516 return (0, 5); # code 5: should be private list
519 elsif($action eq 'manage') {
520 return 1 if $user && $shelf->{owner}==$user;
527 $result= &DelFromShelf( $bibref, $shelfnumber, $user);
529 Removes biblionumbers in passed arrayref from shelf C<$shelfnumber>.
530 If the bib wasn't on that virtualshelves to begin with, nothing happens.
532 Returns 0 if no items have been deleted.
537 my ($bibref, $shelfnumber, $user) = @_;
538 my $dbh = C4::Context->dbh;
539 my $query = qq(SELECT allow_delete_own, allow_delete_other FROM virtualshelves WHERE shelfnumber=?);
540 my $sth= $dbh->prepare($query);
541 $sth->execute($shelfnumber);
542 my ($del_own, $del_oth)= $sth->fetchrow;
546 $query = qq(DELETE FROM virtualshelfcontents
547 WHERE shelfnumber=? AND biblionumber=? AND borrowernumber=?);
548 $sth= $dbh->prepare($query);
549 foreach my $biblionumber (@$bibref) {
550 $sth->execute($shelfnumber, $biblionumber, $user);
551 $r= $sth->rows; #Expect -1, 0 or 1 (-1 means Don't know; count as 1)
552 $t+= ($r==-1)? 1: $r;
556 #includes a check if borrowernumber is null (deleted patron)
557 $query = qq/DELETE FROM virtualshelfcontents
558 WHERE shelfnumber=? AND biblionumber=? AND
559 (borrowernumber IS NULL OR borrowernumber<>?)/;
560 $sth= $dbh->prepare($query);
561 foreach my $biblionumber (@$bibref) {
562 $sth->execute($shelfnumber, $biblionumber, $user);
564 $t+= ($r==-1)? 1: $r;
572 $Number = DelShelf($shelfnumber);
574 This function deletes the shelf number, and all of it's content.
575 Authorization to do so MUST have been checked before calling, while using
576 ShelfPossibleAction with manage parameter.
581 my ($shelfnumber)= @_;
582 return unless $shelfnumber && $shelfnumber =~ /^\d+$/;
583 my $dbh = C4::Context->dbh;
584 my $sth = $dbh->prepare("DELETE FROM virtualshelves WHERE shelfnumber=?");
585 return $sth->execute($shelfnumber);
588 =head2 GetBibliosShelves
590 This finds all the public lists that this bib record is in.
594 sub GetBibliosShelves {
595 my ( $biblionumber ) = @_;
596 my $dbh = C4::Context->dbh;
597 my $sth = $dbh->prepare('
598 SELECT vs.shelfname, vs.shelfnumber
599 FROM virtualshelves vs
600 JOIN virtualshelfcontents vc ON (vs.shelfnumber= vc.shelfnumber)
602 AND vc.biblionumber= ?
604 $sth->execute( $biblionumber );
605 return $sth->fetchall_arrayref({});
610 $howmany= ShelvesMax($context);
612 Tells how much shelves are shown in which context.
613 POPUP refers to addbybiblionumber popup, MGRPAGE is managing page (in opac or
614 staff), COMBO refers to the Add to-combo of search results. MASTHEAD is the
615 main Koha toolbar with Lists button.
621 return SHELVES_POPUP_MAX if $which eq 'POPUP';
622 return SHELVES_MGRPAGE_MAX if $which eq 'MGRPAGE';
623 return SHELVES_COMBO_MAX if $which eq 'COMBO';
624 return SHELVES_MASTHEAD_MAX if $which eq 'MASTHEAD';
625 return SHELVES_MASTHEAD_MAX;
628 =head2 HandleDelBorrower
630 HandleDelBorrower($borrower);
632 When a member is deleted (DelMember in Members.pm), you should call me first.
633 This routine deletes/moves lists and entries for the deleted member/borrower.
634 Lists owned by the borrower are deleted, but entries from the borrower to
635 other lists are kept.
639 sub HandleDelBorrower {
642 my $dbh = C4::Context->dbh;
644 #Delete all lists and all shares of this borrower
645 #Consistent with the approach Koha uses on deleting individual lists
646 #Note that entries in virtualshelfcontents added by this borrower to
647 #lists of others will be handled by a table constraint: the borrower
648 #is set to NULL in those entries.
649 $query="DELETE FROM virtualshelves WHERE owner=?";
650 $dbh->do($query,undef,($borrower));
653 #We could handle the above deletes via a constraint too.
654 #But a new BZ report 11889 has been opened to discuss another approach.
655 #Instead of deleting we could also disown lists (based on a pref).
656 #In that way we could save shared and public lists.
657 #The current table constraints support that idea now.
658 #This pref should then govern the results of other routines such as
664 AddShare($shelfnumber, $key);
666 Adds a share request to the virtualshelves table.
667 Authorization must have been checked, and a key must be supplied. See script
668 opac-shareshelf.pl for an example.
669 This request is not yet confirmed. So it has no borrowernumber, it does have an
675 my ($shelfnumber, $key)= @_;
676 return if !$shelfnumber || !$key;
679 my $dbh = C4::Context->dbh;
680 $sql="DELETE FROM virtualshelfshares WHERE sharedate<NOW() LIMIT 10";
681 #housekeeping: add one, remove max 10 expired ones
683 $sql="INSERT INTO virtualshelfshares (shelfnumber, invitekey, sharedate) VALUES (?, ?, ADDDATE(NOW(),?))";
684 $dbh->do($sql, undef, ($shelfnumber, $key, SHARE_INVITATION_EXPIRY_DAYS));
690 my $result= AcceptShare($shelfnumber, $key, $borrowernumber);
692 Checks acceptation of a share request.
693 Key must be found for this shelf. Invitation must not have expired.
694 Returns true when accepted, false otherwise.
699 my ($shelfnumber, $key, $borrowernumber)= @_;
700 return if !$shelfnumber || !$key || !$borrowernumber;
703 my $dbh = C4::Context->dbh;
705 UPDATE virtualshelfshares
706 SET invitekey=NULL, sharedate=NULL, borrowernumber=?
707 WHERE shelfnumber=? AND invitekey=? AND sharedate>NOW()
709 my $i= $dbh->do($sql, undef, ($borrowernumber, $shelfnumber, $key));
710 return if !defined($i) || !$i || $i eq '0E0'; #not found
716 my $bool= IsSharedList( $shelfnumber );
718 IsSharedList checks if a (private) list has shares.
719 Note that such a check would not be useful for public lists. A public list has
720 no shares, but is visible for anyone by nature..
721 Used to determine the list type in the display of Your lists (all private).
722 Returns boolean value.
727 my ($shelfnumber) = @_;
728 my $dbh = C4::Context->dbh;
729 my $sql="SELECT id FROM virtualshelfshares WHERE shelfnumber=? AND borrowernumber IS NOT NULL";
730 my $sth = $dbh->prepare($sql);
731 $sth->execute($shelfnumber);
732 my ($rv)= $sth->fetchrow_array;
738 RemoveShare( $user, $shelfnumber );
740 RemoveShare removes a share for specific shelf and borrower.
741 Returns true if a record could be deleted.
746 my ($user, $shelfnumber)= @_;
747 my $dbh = C4::Context->dbh;
749 DELETE FROM virtualshelfshares
750 WHERE borrowernumber=? AND shelfnumber=?
752 my $n= $dbh->do($sql,undef,($user, $shelfnumber));
753 return if !defined($n) || !$n || $n eq '0E0'; #nothing removed
760 my ($owner, $category) = @_;
762 # Find out how many shelves total meet the submitted criteria...
764 my $dbh = C4::Context->dbh;
765 my $query = "SELECT count(*) FROM virtualshelves vs ";
768 LEFT JOIN virtualshelfshares sh ON sh.shelfnumber=vs.shelfnumber
769 AND sh.borrowernumber=?
770 WHERE category=1 AND (vs.owner=? OR sh.borrowernumber=?) };
771 @params= ($owner, $owner, $owner);
774 $query.='WHERE category=2';
777 my $sth = $dbh->prepare($query);
778 $sth->execute(@params);
779 my ($total)= $sth->fetchrow;
783 sub _CheckShelfName {
784 my ($name, $cat, $owner, $number)= @_;
786 my $dbh = C4::Context->dbh;
789 SELECT DISTINCT shelfnumber
791 LEFT JOIN virtualshelfshares sh USING (shelfnumber)
792 WHERE shelfname=? AND shelfnumber<>?);
793 if($cat==1 && defined($owner)) {
794 $query.= ' AND (sh.borrowernumber=? OR owner=?) AND category=1';
795 @pars=($name, $number, $owner, $owner);
797 elsif($cat==1 && !defined($owner)) { #owner is null (exceptional)
798 $query.= ' AND owner IS NULL AND category=1';
799 @pars=($name, $number);
802 $query.= ' AND category=2';
803 @pars=($name, $number);
805 my $sth = $dbh->prepare($query);
806 $sth->execute(@pars);
807 return $sth->rows>0? 0: 1;
816 Koha Development Team <http://koha-community.org/>
820 C4::Circulation::Circ2(3)