2 # Please use 8-character tabs for this file (indents are every 4 characters)
4 package C4
::VirtualShelves
;
7 # Copyright 2000-2002 Katipo Communications
9 # This file is part of Koha.
11 # Koha is free software; you can redistribute it and/or modify it under the
12 # terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 2 of the License, or (at your option) any later
16 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
17 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License along
21 # with Koha; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 use vars
qw($VERSION @ISA @EXPORT @EXPORT_OK);
34 # set the version for version checking
39 &GetShelves &GetShelfContents &GetShelf
43 &DelFromShelf &DelShelf
47 &GetShelvesSummary &GetRecentShelves &GetAllShelves
48 &RefreshShelvesSummary &SetShelvesLimit
53 my $dbh = C4
::Context
->dbh;
57 C4::VirtualShelves - Functions for manipulating Koha virtual virtualshelves
61 use C4::VirtualShelves;
65 This module provides functions for manipulating virtual virtualshelves,
66 including creating and deleting virtualshelves, and adding and removing
67 bibs to and from virtualshelves.
73 ($shelflist, $totshelves) = &GetShelves($mincategory, $row_count, $offset, $owner);
74 ($shelfnumber, $shelfhash) = each %{$shelflist};
76 Returns the number of shelves specified by C<$row_count> and C<$offset> as well as the total
77 number of shelves that meet the C<$owner> and C<$mincategory> criteria. C<$mincategory>,
78 C<$row_count>, and C<$offset> are required. C<$owner> must be supplied when C<$mincategory> == 1.
79 When C<$mincategory> is 2 or 3, supply undef as argument for C<$owner>.
80 C<$shelflist>is a reference-to-hash. The keys are the virtualshelves numbers (C<$shelfnumber>, above),
81 and the values (C<$shelfhash>, above) are themselves references-to-hash, with the following keys:
85 =item C<$shelfhash-E<gt>{shelfname}>
87 A string. The name of the shelf.
89 =item C<$shelfhash-E<gt>{count}>
91 The number of virtuals on that virtualshelves.
97 sub GetShelves
($$$$) {
98 my ($mincategory, $row_count, $offset, $owner) = @_;
99 my @params = ($owner, $mincategory, ($offset ?
$offset : 0), $row_count);
100 my @params1 = ($owner, $mincategory);
101 if ($mincategory > 1) {
105 my $total = _shelf_count
($owner, $mincategory);
106 # grab only the shelves meeting the row_count/offset spec...
108 SELECT virtualshelves
.shelfnumber
, virtualshelves
.shelfname
,owner
,surname
,firstname
,virtualshelves
.category
,virtualshelves
.sortfield
,
109 count
(virtualshelfcontents
.biblionumber
) as count
111 LEFT JOIN virtualshelfcontents ON virtualshelves
.shelfnumber
= virtualshelfcontents
.shelfnumber
112 LEFT JOIN borrowers ON virtualshelves
.owner
= borrowers
.borrowernumber
);
113 $query .= ($mincategory == 1) ?
"WHERE owner=? AND category=?" : "WHERE category>=?";
115 GROUP BY virtualshelves
.shelfnumber
116 ORDER BY virtualshelves
.shelfname
118 my $sth2 = $dbh->prepare($query);
119 $sth2->execute(@params);
121 while ( my ( $shelfnumber, $shelfname, $owner, $surname,
122 $firstname, $category, $sortfield, $count ) = $sth2->fetchrow ) {
123 $shelflist{$shelfnumber}->{'shelfname'} = $shelfname;
124 $shelflist{$shelfnumber}->{'count'} = $count;
125 if($count eq 1){ $shelflist{$shelfnumber}->{'single'} = 1; }
126 $shelflist{$shelfnumber}->{'sortfield'} = $sortfield;
127 $shelflist{$shelfnumber}->{'category'} = $category;
128 $shelflist{$shelfnumber}->{'owner'} = $owner;
129 $shelflist{$shelfnumber}->{'surname'} = $surname;
130 $shelflist{$shelfnumber}->{'firstname'} = $firstname;
132 return ( \
%shelflist, $total );
135 =head2 GetShelvesSummary
137 ($shelves, $total) = GetShelvesSummary($mincategory, $row_count, $offset, $owner)
139 Returns the number of shelves specified by C<$row_count> and C<$offset> as well as the total
140 number of shelves that meet the C<$owner> and/or C<$mincategory> criteria. C<$mincategory>,
141 C<$row_count>, and C<$offset> are required. C<$owner> must be supplied when C<$mincategory> == 1.
142 When C<$mincategory> is 2 or 3, supply undef as argument for C<$owner>.
146 sub GetShelvesSummary
($$$$) {
147 my ($mincategory, $row_count, $offset, $owner) = @_;
148 my @params = ($owner, $mincategory, ($offset ?
$offset : 0), $row_count);
149 my @params1 = ($owner, $mincategory);
150 if ($mincategory > 1) {
154 my $total = _shelf_count
($owner, $mincategory);
155 # grab only the shelves meeting the row_count/offset spec...
158 virtualshelves
.shelfnumber
,
159 virtualshelves
.shelfname
,
161 CONCAT
(firstname
, ' ', surname
) AS name
,
162 virtualshelves
.category
,
163 count
(virtualshelfcontents
.biblionumber
) AS count
165 LEFT JOIN virtualshelfcontents ON virtualshelves
.shelfnumber
= virtualshelfcontents
.shelfnumber
166 LEFT JOIN borrowers ON virtualshelves
.owner
= borrowers
.borrowernumber
);
167 $query .= ($mincategory == 1) ?
"WHERE owner=? AND category=?" : "WHERE category>=?";
169 GROUP BY virtualshelves
.shelfnumber
170 ORDER BY virtualshelves
.category
173 my $sth2 = $dbh->prepare($query);
174 $sth2->execute(@params);
175 my $shelves = $sth2->fetchall_arrayref({});
176 return ($shelves, $total);
178 # Probably NOT the final implementation since it is still bulky (repeated hash keys).
179 # might like an array of rows of delimited values:
180 # 1|2||0|blacklist|112
181 # 2|6|Josh Ferraro|51|en_fuego|106
184 =head2 GetRecentShelves
186 ($shelflist, $total) = GetRecentShelves(1, $limit, $owner)
188 This function returns a reference to an array of hashrefs containing specified shelves sorted
189 by the date the shelf was last modified in descending order limited to the number of records
190 specified by C<$row_count>. If calling with C<$mincategory> other than 1, use undef as C<$owner>.
192 This function is intended to return a dataset reflecting the most recently active shelves for
193 the submitted parameters.
197 sub GetRecentShelves
{
198 my ($mincategory, $row_count, $owner) = @_;
199 my $total = _shelf_count
($owner, $mincategory);
202 if (defined $owner) {
203 @params = ($owner, $mincategory);
204 $selection = ' WHERE owner = ? AND category = ?';
206 @params = ( $mincategory);
207 $selection = ' WHERE category >= ? ';
209 my $query = 'SELECT * FROM virtualshelves';
210 $query .= $selection;
211 $query .= ' ORDER BY lastmodified DESC';
213 $query .= ' LIMIT ?';
214 push @params,$row_count;
216 my $sth = $dbh->prepare($query);
217 $sth->execute(@params);
218 my $shelflist = $sth->fetchall_arrayref({});
219 return ( $shelflist, $total );
224 $shelflist = GetAllShelves($owner)
226 This function returns a reference to an array of hashrefs containing all shelves sorted
229 This function is intended to return a dataset reflecting all the shelves for
230 the submitted parameters.
235 my ($category,$owner) = @_;
236 my $query = 'SELECT * FROM virtualshelves WHERE category = ? AND owner = ? ORDER BY shelfname ASC';
237 my $sth = $dbh->prepare( $query );
238 $sth->execute( $category, $owner );
239 return $sth->fetchall_arrayref({});
244 (shelfnumber,shelfname,owner,category,sortfield) = &GetShelf($shelfnumber);
246 Looks up information about the contents of virtual virtualshelves number
249 Returns the database's information on 'virtualshelves' table.
254 my ($shelfnumber) = @_;
256 SELECT shelfnumber
, shelfname
, owner
, category
, sortfield
260 my $sth = $dbh->prepare($query);
261 $sth->execute($shelfnumber);
262 return $sth->fetchrow;
265 =head2 GetShelfContents
267 $biblist = &GetShelfContents($shelfnumber);
269 Looks up information about the contents of virtual virtualshelves number
270 C<$shelfnumber>. Sorted by a field in the biblio table. copyrightdate
273 Returns a reference-to-array, whose elements are references-to-hash,
274 as returned by C<C4::Biblio::GetBiblioFromItemNumber>.
276 Note: the notforloan status comes from the itemtype, and where it equals 0
277 it does not ensure that related items.notforloan status is likewise 0. The
278 caller has to check any items on their own, possibly with CanBookBeIssued
279 from C4::Circulation.
283 sub GetShelfContents
($;$$$) {
284 my ($shelfnumber, $row_count, $offset, $sortfield) = @_;
285 my $dbh=C4
::Context
->dbh();
286 my $sth1 = $dbh->prepare("SELECT count(*) FROM virtualshelfcontents WHERE shelfnumber = ?");
287 $sth1->execute($shelfnumber);
288 my $total = $sth1->fetchrow;
290 my $sth2 = $dbh->prepare('SELECT sortfield FROM virtualshelves WHERE shelfnumber=?');
291 $sth2->execute($shelfnumber);
292 ($sortfield) = $sth2->fetchrow_array;
295 " SELECT vc.biblionumber, vc.shelfnumber, vc.dateadded, itemtypes.*,
296 biblio.*, biblioitems.itemtype, biblioitems.publicationyear as year, biblioitems.publishercode, biblioitems.place, biblioitems.size, biblioitems.pages
297 FROM virtualshelfcontents vc
298 LEFT JOIN biblio ON vc.biblionumber = biblio.biblionumber
299 LEFT JOIN biblioitems ON biblio.biblionumber = biblioitems.biblionumber
300 LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype
301 WHERE vc.shelfnumber=? ";
302 my @params = ($shelfnumber);
304 $query .= " ORDER BY " . $sortfield;
305 $query .= " DESC " if ($sortfield eq 'copyrightdate');
308 $query .= " LIMIT ?, ? ";
309 push (@params, ($offset ?
$offset : 0));
310 push (@params, $row_count);
312 my $sth3 = $dbh->prepare($query);
313 $sth3->execute(@params);
314 return ($sth3->fetchall_arrayref({}), $total);
315 # Like the perldoc says,
316 # returns reference-to-array, where each element is reference-to-hash of the row:
317 # like [ $sth->fetchrow_hashref(), $sth->fetchrow_hashref() ... ]
318 # Suitable for use in TMPL_LOOP.
319 # See http://search.cpan.org/~timb/DBI-1.601/DBI.pm#fetchall_arrayref
320 # or newer, for your version of DBI.
325 $shelfnumber = &AddShelf( $shelfname, $owner, $category);
327 Creates a new virtual virtualshelves with name C<$shelfname>, owner C<$owner> and category
330 Returns a code to know what's happen.
331 * -1 : if this virtualshelves already exist.
332 * $shelfnumber : if success.
337 my ( $shelfname, $owner, $category, $sortfield ) = @_;
341 WHERE shelfname
=? AND owner
=?
343 my $sth = $dbh->prepare($query);
344 $sth->execute($shelfname,$owner);
345 ( $sth->rows ) and return (-1);
347 INSERT INTO virtualshelves
348 (shelfname
,owner
,category
,sortfield
)
351 $sth = $dbh->prepare($query);
352 $sth->execute( $shelfname, $owner, $category, $sortfield );
353 my $shelfnumber = $dbh->{'mysql_insertid'};
354 return ($shelfnumber);
359 &AddToShelf($biblionumber, $shelfnumber);
361 Adds bib number C<$biblionumber> to virtual virtualshelves number
362 C<$shelfnumber>, unless that bib is already on that shelf.
368 my ( $biblionumber, $shelfnumber ) = @_;
369 return unless $biblionumber;
372 FROM virtualshelfcontents
373 WHERE shelfnumber
=? AND biblionumber
=?
375 my $sth = $dbh->prepare($query);
377 $sth->execute( $shelfnumber, $biblionumber );
378 ($sth->rows) and return undef; # already on shelf
380 INSERT INTO virtualshelfcontents
381 (shelfnumber
, biblionumber
, flags
)
385 $sth = $dbh->prepare($query);
386 $sth->execute( $shelfnumber, $biblionumber );
387 $query = qq(UPDATE virtualshelves
388 SET lastmodified
= CURRENT_TIMESTAMP
389 WHERE shelfnumber
= ?
);
390 $sth = $dbh->prepare($query);
391 $sth->execute( $shelfnumber );
396 ModShelf($shelfnumber, $hashref)
398 Where $hashref->{column} = param
400 Modify the value into virtualshelves table with values given
401 from hashref, which each key of the hashref should be
402 the name of a column of virtualshelves.
407 my $shelfnumber = shift;
410 if (exists $shelf->{shelfnumber
}) {
411 carp
"Should not use ModShelf to change shelfnumber";
414 unless (defined $shelfnumber and $shelfnumber =~ /^\d+$/) {
415 carp
"Invalid shelfnumber passed to ModShelf: $shelfnumber";
419 my $query = "UPDATE virtualshelves SET ";
420 my @bind_params = ();
421 my @set_clauses = ();
423 foreach my $column (keys %$shelf) {
424 push @set_clauses, "$column = ?";
425 push @bind_params, $shelf->{$column};
428 if ($#set_clauses == -1) {
429 carp
"No columns to update passed to ModShelf";
432 $query .= join(", ", @set_clauses);
434 $query .= " WHERE shelfnumber = ? ";
435 push @bind_params, $shelfnumber;
437 $debug and warn "ModShelf query:\n $query\n",
438 "ModShelf query args: ", join(',', @bind_params), "\n";
439 my $sth = $dbh->prepare($query);
440 $sth->execute( @bind_params );
443 =head2 ShelfPossibleAction
445 ShelfPossibleAction($loggedinuser, $shelfnumber, $action);
447 C<$loggedinuser,$shelfnumber,$action>
449 $action can be "view" or "manage".
451 Returns 1 if the user can do the $action in the $shelfnumber shelf.
456 sub ShelfPossibleAction
{
457 my ( $user, $shelfnumber, $action ) = @_;
459 SELECT owner
,category
463 my $sth = $dbh->prepare($query);
464 $sth->execute($shelfnumber);
465 my ( $owner, $category ) = $sth->fetchrow;
467 my $borrower = C4
::Members
::GetMemberDetails
($user);
468 return 0 if not defined($user);
469 return 1 if ( $category >= 3); # open list
470 return 1 if (($category >= 2) and
471 defined($action) and $action eq 'view'); # public list, anybody can view
472 return 1 if (($category >= 2) and defined($user) and ($borrower->{authflags
}->{superlibrarian
} || $user == 0)); # public list, superlibrarian can edit/delete
473 return 1 if (defined($user) and $owner eq $user ); # user owns this list. Check last.
479 &DelFromShelf( $biblionumber, $shelfnumber);
481 Removes bib number C<$biblionumber> from virtual virtualshelves number
482 C<$shelfnumber>. If the bib wasn't on that virtualshelves to begin with,
489 my ( $biblionumber, $shelfnumber ) = @_;
491 DELETE FROM virtualshelfcontents
492 WHERE shelfnumber
=? AND biblionumber
=?
494 my $sth = $dbh->prepare($query);
495 $sth->execute( $shelfnumber, $biblionumber );
498 =head2 DelShelf (old version)
500 ($status, $msg) = &DelShelf($shelfnumber);
502 Deletes virtual virtualshelves number C<$shelfnumber>. The virtualshelves must
505 Returns a two-element array, where C<$status> is 0 if the operation
506 was successful, or non-zero otherwise. C<$msg> is "Done" in case of
507 success, or an error message giving the reason for failure.
509 =head2 DelShelf (current version)
511 $Number = DelShelf($shelfnumber);
513 This function deletes the shelf number, and all of it's content.
519 carp
"DelShelf called without valid argument (shelfnumber)";
522 my $sth = $dbh->prepare("DELETE FROM virtualshelves WHERE shelfnumber=?");
523 return $sth->execute(shift);
528 This finds all the public lists that this bib record is in.
532 sub GetBibliosShelves
{
533 my ( $biblionumber ) = @_;
534 my $dbh = C4
::Context
->dbh;
535 my $sth = $dbh->prepare('
536 SELECT vs.shelfname, vs.shelfnumber
537 FROM virtualshelves vs
538 JOIN virtualshelfcontents vc ON (vs.shelfnumber= vc.shelfnumber)
539 WHERE vs.category != 1
540 AND vc.biblionumber= ?
542 $sth->execute( $biblionumber );
543 return $sth->fetchall_arrayref({});
546 =head2 RefreshShelvesSummary
548 ($total, $pubshelves, $barshelves) = RefreshShelvesSummary($sessionID, $loggedinuser, $row_count);
550 Updates the current session and userenv with the most recent shelves
552 Returns the total number of shelves stored in the session/userenv along with two references each to an
553 array of hashes, one containing the C<$loggedinuser>'s private shelves and one containing all public/open shelves.
555 This function is used in conjunction with the 'Lists' button in masthead.inc.
559 sub RefreshShelvesSummary
($$$) {
561 my ($sessionID, $loggedinuser, $row_count) = @_;
562 my $session = C4
::Auth
::get_session
($sessionID);
563 my ($total, $totshelves, $barshelves, $pubshelves);
565 ($barshelves, $totshelves) = GetRecentShelves
(1, $row_count, $loggedinuser);
566 $total->{'bartotal'} = $totshelves;
567 ($pubshelves, $totshelves) = GetRecentShelves
(2, $row_count, undef);
568 $total->{'pubtotal'} = $totshelves;
570 # Update the current session with the latest shelves...
571 $session->param('barshelves', $barshelves);
572 $session->param('pubshelves', $pubshelves);
573 $session->param('totshelves', $total);
575 # likewise the userenv...
576 C4
::Context
->set_shelves_userenv('bar',$barshelves);
577 C4
::Context
->set_shelves_userenv('pub',$pubshelves);
578 C4
::Context
::set_shelves_userenv
('tot',$total);
580 return ($total, $pubshelves, $barshelves);
585 sub _shelf_count
($$) {
587 # Find out how many shelves total meet the submitted criteria...
588 my $query = "SELECT count(*) FROM virtualshelves";
589 $query .= ($params[1] > 1) ?
" WHERE category >= ?" : " WHERE owner=? AND category=?";
590 shift @params if $params[1] > 1;
591 my $sth = $dbh->prepare($query);
592 $sth->execute(@params);
593 my $total = $sth->fetchrow;
597 sub _biblionumber_sth
{
599 my $query = 'select biblionumber from virtualshelfcontents where shelfnumber = ?';
600 my $dbh = C4
::Context
->dbh;
601 my $sth = $dbh->prepare($query)
603 $sth->execute( $shelf )
608 sub each_biblionumbers
(&$) {
609 my ($code,$shelf) = @_;
610 my $ref = _biblionumber_sth
($shelf)->fetchall_arrayref;
623 Koha Development Team <http://koha-community.org/>
627 C4::Circulation::Circ2(3)