VirtualShelves.pm - expanded SQL for shelf contents, fixes bug of no itemtypes displa...
[koha.git] / C4 / VirtualShelves.pm
1 # -*- tab-width: 8 -*-
2 # Please use 8-character tabs for this file (indents are every 4 characters)
3
4 package C4::VirtualShelves;
5
6
7 # Copyright 2000-2002 Katipo Communications
8 #
9 # This file is part of Koha.
10 #
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
14 # version.
15 #
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.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
22 # Suite 330, Boston, MA  02111-1307 USA
23
24 use strict;
25 use C4::Context;
26 use C4::Circulation;
27 use vars qw($VERSION @ISA @EXPORT);
28
29 BEGIN {
30         # set the version for version checking
31         $VERSION = 3.01;
32         require Exporter;
33         @ISA    = qw(Exporter);
34         @EXPORT = qw(
35         &GetShelves &GetShelfContents &GetShelf
36
37         &AddToShelf &AddToShelfFromBiblio &AddShelf
38
39         &ModShelf
40         &ShelfPossibleAction
41         &DelFromShelf &DelShelf
42         );
43 }
44
45 my $dbh = C4::Context->dbh;
46
47 =head1 NAME
48
49 C4::VirtualShelves - Functions for manipulating Koha virtual virtualshelves
50
51 =head1 SYNOPSIS
52
53   use C4::VirtualShelves;
54
55 =head1 DESCRIPTION
56
57 This module provides functions for manipulating virtual virtualshelves,
58 including creating and deleting virtualshelves, and adding and removing
59 items to and from virtualshelves.
60
61 =head1 FUNCTIONS
62
63 =over 2
64
65 =item GetShelves
66
67   $shelflist = &GetShelves($owner, $mincategory);
68   ($shelfnumber, $shelfhash) = each %{$shelflist};
69
70 Looks up the virtual virtualshelves, and returns a summary. C<$shelflist>
71 is a reference-to-hash. The keys are the virtualshelves numbers
72 (C<$shelfnumber>, above), and the values (C<$shelfhash>, above) are
73 themselves references-to-hash, with the following keys:
74
75 C<mincategory> : 2 if the list is for "look". 3 if the list is for "Select virtualshelves for adding a virtual".
76 virtualshelves of the owner are always selected, whatever the category
77
78 =over 4
79
80 =item C<$shelfhash-E<gt>{shelfname}>
81
82 A string. The name of the shelf.
83
84 =item C<$shelfhash-E<gt>{count}>
85
86 The number of virtuals on that virtualshelves.
87
88 =back
89
90 =cut
91
92 #'
93 # FIXME - Wouldn't it be more intuitive to return a list, rather than
94 # a reference-to-hash? The shelf number can be just another key in the
95 # hash.
96
97 sub GetShelves {
98     my ( $owner, $mincategory ) = @_;
99
100     my $query = qq(
101         SELECT virtualshelves.shelfnumber, virtualshelves.shelfname,owner,surname,firstname,virtualshelves.category,virtualshelves.sortfield,
102                count(virtualshelfcontents.biblionumber) as count
103         FROM   virtualshelves
104             LEFT JOIN   virtualshelfcontents ON virtualshelves.shelfnumber = virtualshelfcontents.shelfnumber
105             LEFT JOIN   borrowers ON virtualshelves.owner = borrowers.borrowernumber
106         WHERE  owner=? OR category>=?
107         GROUP BY virtualshelves.shelfnumber
108         ORDER BY virtualshelves.category, virtualshelves.shelfname, borrowers.firstname, borrowers.surname
109     );
110     my $sth = $dbh->prepare($query);
111     $sth->execute( $owner, $mincategory );
112     my %shelflist;
113     while (
114         my (
115             $shelfnumber, $shelfname, $owner, $surname,
116             $firstname,   $category,  $sortfield, $count
117         )
118         = $sth->fetchrow
119       )
120     {
121         $shelflist{$shelfnumber}->{'shelfname'} = $shelfname;
122         $shelflist{$shelfnumber}->{'count'}     = $count;
123         $shelflist{$shelfnumber}->{'sortfield'}     = $sortfield;
124         $shelflist{$shelfnumber}->{'category'}  = $category;
125         $shelflist{$shelfnumber}->{'owner'}     = $owner;
126         $shelflist{$shelfnumber}->{'surname'}     = $surname;
127         $shelflist{$shelfnumber}->{'firstname'}   = $firstname;
128     }
129     return ( \%shelflist );
130 }
131
132 =item GetShelf
133
134   (shelfnumber,shelfname,owner,category) = &GetShelf($shelfnumber);
135
136 Looks up information about the contents of virtual virtualshelves number
137 C<$shelfnumber>
138
139 Returns the database's information on 'virtualshelves' table.
140
141 =cut
142
143 sub GetShelf {
144     my ($shelfnumber) = @_;
145     my $query = qq(
146         SELECT shelfnumber,shelfname,owner,category,sortfield
147         FROM   virtualshelves
148         WHERE  shelfnumber=?
149     );
150     my $sth = $dbh->prepare($query);
151     $sth->execute($shelfnumber);
152     return $sth->fetchrow;
153 }
154
155 =item GetShelfContents
156
157   $itemlist = &GetShelfContents($shelfnumber);
158
159 Looks up information about the contents of virtual virtualshelves number
160 C<$shelfnumber>.  Sorted by a field in the biblio table.  copyrightdate 
161 gives a desc sort.
162
163 Returns a reference-to-array, whose elements are references-to-hash,
164 as returned by C<C4::Biblio::GetBiblioFromItemNumber>.
165
166 Note: the notforloan status comes from the itemtype, and where it equals 0
167 it does not ensure that related items.notforloan status is likewise 0. The
168 caller has to check any items on their own, possibly with CanBookBeIssued
169 from C4::Circulation.
170
171 =cut
172
173 sub GetShelfContents {
174     my ( $shelfnumber ,$sortfield) = @_;
175     my $dbh=C4::Context->dbh();
176         if(!$sortfield) {
177                 my $sthsort = $dbh->prepare('select sortfield from virtualshelves where shelfnumber=?');
178                 $sthsort->execute($shelfnumber);
179                 ($sortfield) = $sthsort->fetchrow_array;
180         }
181     my $query =
182        " SELECT vc.biblionumber, vc.shelfnumber,
183                                 biblio.*, biblioitems.itemtype, itemtypes.*
184          FROM   virtualshelfcontents vc
185                  LEFT JOIN biblio      ON      vc.biblionumber =      biblio.biblionumber
186                  LEFT JOIN biblioitems ON  biblio.biblionumber = biblioitems.biblionumber
187                  LEFT JOIN itemtypes   ON biblioitems.itemtype = itemtypes.itemtype
188          WHERE  vc.shelfnumber=? ";
189         if($sortfield) {
190                 $query .= " ORDER BY `$sortfield` ";
191                 $query .= " DESC " if ($sortfield eq 'copyrightdate');
192         }
193     my $sth = $dbh->prepare($query);
194         $sth->execute($shelfnumber);
195         return $sth->fetchall_arrayref({});     
196         # Like the perldoc says,
197         # returns reference-to-array, where each element is reference-to-hash of the row:
198         #   like [ $sth->fetchrow_hashref(), $sth->fetchrow_hashref() ... ] 
199         # Suitable for use in TMPL_LOOP.
200         # See http://search.cpan.org/~timb/DBI-1.601/DBI.pm#fetchall_arrayref
201         # or newer, for your version of DBI.
202 }
203
204 =item AddShelf
205
206   $shelfnumber = &AddShelf( $shelfname, $owner, $category);
207
208 Creates a new virtual virtualshelves with name C<$shelfname>, owner C<$owner> and category
209 C<$category>.
210
211 Returns a code to know what's happen.
212     * -1 : if this virtualshelves already exist.
213     * $shelfnumber : if success.
214
215 =cut
216
217 sub AddShelf {
218     my ( $shelfname, $owner, $category ) = @_;
219     my $query = qq(
220         SELECT *
221         FROM   virtualshelves
222         WHERE  shelfname=? AND owner=?
223     );
224     my $sth = $dbh->prepare($query);
225     $sth->execute($shelfname,$owner);
226     ( $sth->rows ) and return (-1);
227     $query = qq(
228         INSERT INTO virtualshelves
229             (shelfname,owner,category)
230         VALUES (?,?,?)
231     );
232     $sth = $dbh->prepare($query);
233     $sth->execute( $shelfname, $owner, $category );
234     my $shelfnumber = $dbh->{'mysql_insertid'};
235     return ($shelfnumber);
236 }
237
238 =item AddToShelf
239
240   &AddToShelf($biblionumber, $shelfnumber);
241
242 Adds item number C<$biblionumber> to virtual virtualshelves number
243 C<$shelfnumber>, unless that item is already on that shelf.
244
245 =cut
246
247 #'
248 sub AddToShelf {
249     my ( $biblionumber, $shelfnumber ) = @_;
250     return unless $biblionumber;
251     my $query = qq(
252         SELECT *
253         FROM   virtualshelfcontents
254         WHERE  shelfnumber=? AND biblionumber=?
255     );
256     my $sth = $dbh->prepare($query);
257
258     $sth->execute( $shelfnumber, $biblionumber );
259     unless ( $sth->rows ) {
260         # already on shelf
261         my $query = qq(
262             INSERT INTO virtualshelfcontents
263                 (shelfnumber, biblionumber, flags)
264             VALUES
265                 (?, ?, 0)
266         );
267         $sth = $dbh->prepare($query);
268         $sth->execute( $shelfnumber, $biblionumber );
269     }
270 }
271
272 =item AddToShelfFromBiblio
273  
274     &AddToShelfFromBiblio($biblionumber, $shelfnumber)
275
276     this function allow to add a virtual into the shelf number $shelfnumber
277     from biblionumber.
278
279 =cut
280
281 sub AddToShelfFromBiblio {
282     my ( $biblionumber, $shelfnumber ) = @_;
283     return unless $biblionumber;
284     my $query = qq(
285         SELECT *
286         FROM   virtualshelfcontents
287         WHERE  shelfnumber=? AND biblionumber=?
288     );
289     my $sth = $dbh->prepare($query);
290     $sth->execute( $shelfnumber, $biblionumber );
291     unless ( $sth->rows ) {
292         my $query =qq(
293             INSERT INTO virtualshelfcontents
294                 (shelfnumber, biblionumber, flags)
295             VALUES
296                 (?, ?, 0)
297         );
298         $sth = $dbh->prepare($query);
299         $sth->execute( $shelfnumber, $biblionumber );
300     }
301 }
302
303 =item ModShelf
304
305 ModShelf($shelfnumber, $shelfname, $owner, $category )
306
307 Modify the value into virtualshelves table with values given on input arg.
308
309 =cut
310
311 sub ModShelf {
312     my ( $shelfnumber, $shelfname, $owner, $category, $sortfield ) = @_;
313     my $query = qq(
314         UPDATE virtualshelves
315         SET    shelfname=?,owner=?,category=?,sortfield=?
316         WHERE  shelfnumber=?
317     );
318         my $sth = $dbh->prepare($query);
319     $sth->execute( $shelfname, $owner, $category, $sortfield, $shelfnumber );
320 }
321
322 =item DelShelf
323
324   ($status) = &DelShelf($shelfnumber);
325
326 Deletes virtual virtualshelves number C<$shelfnumber>. The virtualshelves must
327 be empty.
328
329 Returns a two-element array, where C<$status> is 0 if the operation
330 was successful, or non-zero otherwise. C<$msg> is "Done" in case of
331 success, or an error message giving the reason for failure.
332
333 =cut
334
335
336 =item ShelfPossibleAction
337
338 ShelfPossibleAction($loggedinuser, $shelfnumber, $action);
339
340 C<$loggedinuser,$shelfnumber,$action>
341
342 $action can be "view" or "manage".
343
344 Returns 1 if the user can do the $action in the $shelfnumber shelf.
345 Returns 0 otherwise.
346
347 =cut
348
349 sub ShelfPossibleAction {
350     my ( $user, $shelfnumber, $action ) = @_;
351     my $query = qq(
352         SELECT owner,category
353         FROM   virtualshelves
354         WHERE  shelfnumber=?
355     );
356     my $sth = $dbh->prepare($query);
357     $sth->execute($shelfnumber);
358     my ( $owner, $category ) = $sth->fetchrow;
359     return 1 if (($category >= 3 or $owner eq $user) && $action eq 'manage' );
360     return 1 if (($category >= 2 or $owner eq $user) && $action eq 'view' );
361     return 0;
362 }
363
364 =item DelFromShelf
365
366   &DelFromShelf( $biblionumber, $shelfnumber);
367
368 Removes item number C<$biblionumber> from virtual virtualshelves number
369 C<$shelfnumber>. If the item wasn't on that virtualshelves to begin with,
370 nothing happens.
371
372 =cut
373
374 #'
375 sub DelFromShelf {
376     my ( $biblionumber, $shelfnumber ) = @_;
377     my $query = qq(
378         DELETE FROM virtualshelfcontents
379         WHERE  shelfnumber=? AND biblionumber=?
380     );
381     my $sth = $dbh->prepare($query);
382     $sth->execute( $shelfnumber, $biblionumber );
383 }
384
385 =head2 DelShelf
386
387   $Number = DelShelf($shelfnumber);
388
389     this function delete the shelf number, and all of it's content
390
391 =cut
392
393 #'
394 sub DelShelf {
395         my ( $shelfnumber ) = @_;
396         my $sth = $dbh->prepare("DELETE FROM virtualshelves WHERE shelfnumber=?");
397         $sth->execute($shelfnumber);
398         return 0;
399 }
400
401 END { }    # module clean-up code here (global destructor)
402
403 1;
404
405 __END__
406
407 =back
408
409 =head1 AUTHOR
410
411 Koha Developement team <info@koha.org>
412
413 =head1 SEE ALSO
414
415 C4::Circulation::Circ2(3)
416
417 =cut