View | Details | Raw Unified | Return to bug 10389
Collapse All | Expand All

(-)a/C4/VirtualShelves.pm (-1 / +74 lines)
Lines 44-50 BEGIN { Link Here
44
            &ModShelf
44
            &ModShelf
45
            &ShelfPossibleAction
45
            &ShelfPossibleAction
46
            &DelFromShelf &DelShelf
46
            &DelFromShelf &DelShelf
47
            &GetBibliosShelves &AddShare
47
            &GetBibliosShelves &AddShare &AcceptShare &IsSharedList
48
    );
48
    );
49
        @EXPORT_OK = qw(
49
        @EXPORT_OK = qw(
50
            &GetAllShelves &ShelvesMax
50
            &GetAllShelves &ShelvesMax
Lines 434-439 ShelfPossibleAction($loggedinuser, $shelfnumber, $action); Link Here
434
C<$loggedinuser,$shelfnumber,$action>
434
C<$loggedinuser,$shelfnumber,$action>
435
435
436
$action can be "view", "add", "delete", "manage", "new_public", "new_private".
436
$action can be "view", "add", "delete", "manage", "new_public", "new_private".
437
New additional actions are: invite, acceptshare.
437
Note that add/delete here refers to adding/deleting entries from the list. Deleting the list itself falls under manage.
438
Note that add/delete here refers to adding/deleting entries from the list. Deleting the list itself falls under manage.
438
new_public and new_private refers to creating a new public or private list.
439
new_public and new_private refers to creating a new public or private list.
439
The distinction between deleting your own entries from the list or entries from
440
The distinction between deleting your own entries from the list or entries from
Lines 441-446 others is made in DelFromShelf. Link Here
441
442
442
Returns 1 if the user can do the $action in the $shelfnumber shelf.
443
Returns 1 if the user can do the $action in the $shelfnumber shelf.
443
Returns 0 otherwise.
444
Returns 0 otherwise.
445
For the actions invite and acceptshare a second errorcode is returned if the
446
result is false. See opac-shareshelf.pl
444
447
445
=cut
448
=cut
446
449
Lines 490-495 sub ShelfPossibleAction { Link Here
490
        #DelFromShelf checks the situation per biblio
493
        #DelFromShelf checks the situation per biblio
491
        return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
494
        return 1 if $user>0 && ($shelf->{allow_delete_own}==1 || $shelf->{allow_delete_other}==1);
492
    }
495
    }
496
    elsif($action eq 'invite') {
497
        #for sharing you must be the owner and the list must be private
498
        if( $shelf->{category}==1 ) {
499
            return 1 if $shelf->{owner}==$user;
500
            return (0, 4); # code 4: should be owner
501
        }
502
        else {
503
            return (0, 5); # code 5: should be private list
504
        }
505
    }
506
    elsif($action eq 'acceptshare') {
507
        #the key for accepting is checked later in AcceptShare
508
        #you must not be the owner, list must be private
509
        if( $shelf->{category}==1 ) {
510
            return (0, 8) if $shelf->{owner}==$user;
511
                #code 8: should not be owner
512
            return 1;
513
        }
514
        else {
515
            return (0, 5); # code 5: should be private list
516
        }
517
    }
493
    elsif($action eq 'manage') {
518
    elsif($action eq 'manage') {
494
        return 1 if $user && $shelf->{owner}==$user;
519
        return 1 if $user && $shelf->{owner}==$user;
495
    }
520
    }
Lines 667-672 sub AddShare { Link Here
667
    $dbh->do($sql, undef, ($shelfnumber, $key, SHARE_INVITATION_EXPIRY_DAYS));
692
    $dbh->do($sql, undef, ($shelfnumber, $key, SHARE_INVITATION_EXPIRY_DAYS));
668
}
693
}
669
694
695
=head2 AcceptShare
696
697
     my $result= AcceptShare($shelfnumber, $key, $borrowernumber);
698
699
Checks acceptation of a share request.
700
Key must be found for this shelf. Invitation must not have expired.
701
Returns true when accepted, false otherwise.
702
703
=cut
704
705
sub AcceptShare {
706
    my ($shelfnumber, $key, $borrowernumber)= @_;
707
    return if !$shelfnumber || !$key || !$borrowernumber;
708
709
    my $sql;
710
    my $dbh = C4::Context->dbh;
711
    $sql="
712
UPDATE virtualshelfshares
713
SET invitekey=NULL, sharedate=NULL, borrowernumber=?
714
WHERE shelfnumber=? AND invitekey=? AND sharedate>NOW()
715
    ";
716
    my $i= $dbh->do($sql, undef, ($borrowernumber, $shelfnumber, $key));
717
    return if !defined($i) || !$i || $i eq '0E0'; #not found
718
    return 1;
719
}
720
721
=head2 IsSharedList
722
723
     my $bool= IsSharedList( $shelfnumber );
724
725
IsSharedList checks if a (private) list has shares.
726
Note that such a check would not be useful for public lists. A public list has
727
no shares, but is visible for anyone by nature..
728
Used to determine the list type in the display of Your lists (all private).
729
Returns boolean value.
730
731
=cut
732
733
sub IsSharedList {
734
    my ($shelfnumber) = @_;
735
    my $dbh = C4::Context->dbh;
736
    my $sql="SELECT id FROM virtualshelfshares WHERE shelfnumber=? AND borrowernumber IS NOT NULL";
737
    my $sth = $dbh->prepare($sql);
738
    $sth->execute($shelfnumber);
739
    my ($rv)= $sth->fetchrow_array;
740
    return defined($rv);
741
}
742
670
# internal subs
743
# internal subs
671
744
672
sub _shelf_count {
745
sub _shelf_count {
(-)a/C4/VirtualShelves/Page.pm (+1 lines)
Lines 434-439 sub shelfpage { Link Here
434
        $shelflist->{$element}->{ownername} = defined($member) ? $member->{firstname} . " " . $member->{surname} : '';
434
        $shelflist->{$element}->{ownername} = defined($member) ? $member->{firstname} . " " . $member->{surname} : '';
435
        $numberCanManage++ if $canmanage;    # possibly outmoded
435
        $numberCanManage++ if $canmanage;    # possibly outmoded
436
        if ( $shelflist->{$element}->{'category'} eq '1' ) {
436
        if ( $shelflist->{$element}->{'category'} eq '1' ) {
437
            $shelflist->{$element}->{shares} = IsSharedList($element);
437
            push( @shelveslooppriv, $shelflist->{$element} );
438
            push( @shelveslooppriv, $shelflist->{$element} );
438
        } else {
439
        } else {
439
            push( @shelvesloop, $shelflist->{$element} );
440
            push( @shelvesloop, $shelflist->{$element} );
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (-1 / +1 lines)
Lines 509-515 OPAC: Link Here
509
              choices:
509
              choices:
510
                  no: "Don't allow"
510
                  no: "Don't allow"
511
                  yes: Allow
511
                  yes: Allow
512
            - opac users to share private lists with other patrons. This feature is not active yet but will be released soon
512
            - opac users to share private lists with other patrons.
513
513
514
    Privacy:
514
    Privacy:
515
        -
515
        -
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt (-1 / +1 lines)
Lines 544-550 function placeHold () { Link Here
544
        <td><a href="shelves.pl?[% IF ( shelveslooppri.showprivateshelves ) %]display=privateshelves&amp;[% END %]viewshelf=[% shelveslooppri.shelf %]&amp;shelfoff=[% shelfoff %]">[% shelveslooppri.shelfname |html %]</a></td>
544
        <td><a href="shelves.pl?[% IF ( shelveslooppri.showprivateshelves ) %]display=privateshelves&amp;[% END %]viewshelf=[% shelveslooppri.shelf %]&amp;shelfoff=[% shelfoff %]">[% shelveslooppri.shelfname |html %]</a></td>
545
        <td>[% shelveslooppri.count %] item(s)</td>
545
        <td>[% shelveslooppri.count %] item(s)</td>
546
        <td>[% IF ( shelveslooppri.sortfield == "author" ) %]Author[% ELSIF ( shelveslooppri.sortfield == "copyrightdate" ) %]Year[% ELSIF (shelveslooppri.sortfield == "itemcallnumber") %]Call number[% ELSE %]Title[% END %]</td>
546
        <td>[% IF ( shelveslooppri.sortfield == "author" ) %]Author[% ELSIF ( shelveslooppri.sortfield == "copyrightdate" ) %]Year[% ELSIF (shelveslooppri.sortfield == "itemcallnumber") %]Call number[% ELSE %]Title[% END %]</td>
547
        <td>[% IF ( shelveslooppri.viewcategory1 ) %]Private[% END %]
547
        <td>[% IF ( shelveslooppri.viewcategory1 ) %][% IF !shelveslooppri.shares %]Private[% ELSE %]Shared[% END %][% END %]
548
			[% IF ( shelveslooppri.viewcategory2 ) %]Public[% END %]
548
			[% IF ( shelveslooppri.viewcategory2 ) %]Public[% END %]
549
		</td>
549
		</td>
550
        <td>
550
        <td>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shareshelf.tt (-4 / +3 lines)
Lines 19-24 Link Here
19
        [% IF errcode==4 %]<div class="dialog alert">You can only share a list if you are the owner.</div>[% END %]
19
        [% IF errcode==4 %]<div class="dialog alert">You can only share a list if you are the owner.</div>[% END %]
20
        [% IF errcode==5 %]<div class="dialog alert">You cannot share a public list.</div>[% END %]
20
        [% IF errcode==5 %]<div class="dialog alert">You cannot share a public list.</div>[% END %]
21
        [% IF errcode==6 %]<div class="dialog alert">Sorry, but you did not enter any valid email address.</div>[% END %]
21
        [% IF errcode==6 %]<div class="dialog alert">Sorry, but you did not enter any valid email address.</div>[% END %]
22
        [% IF errcode==7 %]<div class="dialog alert">Sorry, but we could not accept this key. The invitation may have expired. Contact the patron who sent you the invitation.</div>[% END %]
23
        [% IF errcode==8 %]<div class="dialog alert">As owner of a list you cannot accept an invitation for sharing it.</div>[% END %]
22
24
23
    [% ELSIF op=='invite' %]
25
    [% ELSIF op=='invite' %]
24
        <form method="post" onsubmit="return $('#invite_address').val().trim()!='';">
26
        <form method="post" onsubmit="return $('#invite_address').val().trim()!='';">
Lines 45-54 Link Here
45
        <p>You will be notified if someone accepts your share within two weeks.</p>
47
        <p>You will be notified if someone accepts your share within two weeks.</p>
46
48
47
    [% ELSIF op=='accept' %]
49
    [% ELSIF op=='accept' %]
48
        [%# TODO: Replace the following two lines %]
50
        [%# Nothing to do: we already display an error or we redirect. %]
49
        <p>Thank you for testing this feature.</p>
50
        <p>Your signoff will certainly help in finishing the remaining part!</p>
51
52
    [% END %]
51
    [% END %]
53
[%# End of essential part %]
52
[%# End of essential part %]
54
53
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-shelves.tt (-5 / +6 lines)
Lines 577-585 $(document).ready(function() { Link Here
577
                  <ul class="link-tabs">
577
                  <ul class="link-tabs">
578
                  [% IF ( opacuserlogin ) %]
578
                  [% IF ( opacuserlogin ) %]
579
                  [% IF ( showprivateshelves ) %]
579
                  [% IF ( showprivateshelves ) %]
580
                    <li id="privateshelves_tab" class="on"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves">Your private lists</a></li>
580
                    <li id="privateshelves_tab" class="on"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves">Your lists</a></li>
581
                  [% ELSE %]
581
                  [% ELSE %]
582
                    <li id="privateshelves_tab" class="off"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves">Your private lists</a></li>
582
                    <li id="privateshelves_tab" class="off"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves">Your lists</a></li>
583
                  [% END %]
583
                  [% END %]
584
                  [% END %]
584
                  [% END %]
585
                  [% IF ( showpublicshelves ) %]
585
                  [% IF ( showpublicshelves ) %]
Lines 604-610 $(document).ready(function() { Link Here
604
                          <th>List name</th>
604
                          <th>List name</th>
605
                          <th>Contents</th>
605
                          <th>Contents</th>
606
                          <th>Type</th>
606
                          <th>Type</th>
607
                          <th>&nbsp;</th>
607
                          <th>Options</th>
608
                        </tr>
608
                        </tr>
609
                        [% FOREACH shelveslooppri IN shelveslooppriv %]
609
                        [% FOREACH shelveslooppri IN shelveslooppriv %]
610
                          [% UNLESS ( loop.odd ) %]
610
                          [% UNLESS ( loop.odd ) %]
Lines 615-621 $(document).ready(function() { Link Here
615
                              <td><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves&amp;viewshelf=[% shelveslooppri.shelf %]&amp;sortfield=[% shelveslooppri.sortfield %]">[% shelveslooppri.shelfname |html %]</a></td>
615
                              <td><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves&amp;viewshelf=[% shelveslooppri.shelf %]&amp;sortfield=[% shelveslooppri.sortfield %]">[% shelveslooppri.shelfname |html %]</a></td>
616
                              <td>[% IF ( shelveslooppri.count ) %][% shelveslooppri.count %] [% IF ( shelveslooppri.single ) %]item[% ELSE %]items[% END %][% ELSE %]Empty[% END %]</td>
616
                              <td>[% IF ( shelveslooppri.count ) %][% shelveslooppri.count %] [% IF ( shelveslooppri.single ) %]item[% ELSE %]items[% END %][% ELSE %]Empty[% END %]</td>
617
                              <td>
617
                              <td>
618
                                [% IF ( shelveslooppri.viewcategory1 ) %]Private[% END %]
618
                                [% IF ( shelveslooppri.viewcategory1 ) %][% IF !shelveslooppri.shares %]Private[% ELSE %]Shared[% END %][% END %]
619
                                [% IF ( shelveslooppri.viewcategory2 ) %]Public[% END %]
619
                                [% IF ( shelveslooppri.viewcategory2 ) %]Public[% END %]
620
                              </td>
620
                              </td>
621
                              <td>
621
                              <td>
Lines 677-683 $(document).ready(function() { Link Here
677
                        <tr>
677
                        <tr>
678
                          <th>List name</th>
678
                          <th>List name</th>
679
                          <th>Contents</th>
679
                          <th>Contents</th>
680
                          <th>Type</th><th>&nbsp;</th>
680
                          <th>Type</th>
681
                          <th>Options</th>
681
                        </tr>
682
                        </tr>
682
                    [% FOREACH shelvesloo IN shelvesloop %]
683
                    [% FOREACH shelvesloo IN shelvesloop %]
683
                      [% UNLESS ( loop.odd ) %]
684
                      [% UNLESS ( loop.odd ) %]
(-)a/opac/opac-shareshelf.pl (-19 / +28 lines)
Lines 34-40 use C4::VirtualShelves; Link Here
34
#-------------------------------------------------------------------------------
34
#-------------------------------------------------------------------------------
35
35
36
my $query= new CGI;
36
my $query= new CGI;
37
my ($shelfname, $owner);
37
my $shelfname;
38
my ($template, $loggedinuser, $cookie);
38
my ($template, $loggedinuser, $cookie);
39
my $errcode=0;
39
my $errcode=0;
40
my (@addr, $fail_addr, @newkey);
40
my (@addr, $fail_addr, @newkey);
Lines 49-65 my $key= $query->param('key')||''; Link Here
49
49
50
check_common_errors();
50
check_common_errors();
51
load_template("opac-shareshelf.tmpl");
51
load_template("opac-shareshelf.tmpl");
52
(undef, $shelfname)= GetShelf($shelfnumber);
52
if($errcode) {
53
if($errcode) {
53
    #nothing to do
54
    #nothing to do
54
}
55
}
55
elsif($op eq 'invite') {
56
elsif($op eq 'invite') {
56
    show_invite();
57
    check_invite();
57
}
58
}
58
elsif($op eq 'conf_invite') {
59
elsif($op eq 'conf_invite') {
59
    confirm_invite();
60
    check_invite();
61
    confirm_invite() if !$errcode;
60
}
62
}
61
elsif($op eq 'accept') {
63
elsif($op eq 'accept') {
62
    show_accept();
64
    do_accept();
63
}
65
}
64
load_template_vars();
66
load_template_vars();
65
output_html_with_http_headers $query, $cookie, $template->output;
67
output_html_with_http_headers $query, $cookie, $template->output;
Lines 81-92 sub check_common_errors { Link Here
81
    }
83
    }
82
}
84
}
83
85
84
sub show_invite {
86
sub check_invite {
85
    return unless check_owner_category();
87
    my @rv= ShelfPossibleAction($loggedinuser, $shelfnumber, 'invite');
88
    $errcode= $rv[1] if !$rv[0];
89
        #errorcode 4: should be owner
90
        #errorcode 5: should be private list
86
}
91
}
87
92
88
sub confirm_invite {
93
sub confirm_invite {
89
    return unless check_owner_category();
90
    process_addrlist();
94
    process_addrlist();
91
    if(@addr) {
95
    if(@addr) {
92
        send_invitekey();
96
        send_invitekey();
Lines 96-103 sub confirm_invite { Link Here
96
    }
100
    }
97
}
101
}
98
102
99
sub show_accept {
103
sub do_accept {
100
    #TODO Add some code here to accept an invitation (followup report)
104
    my @rv= ShelfPossibleAction($loggedinuser, $shelfnumber, 'acceptshare');
105
    $errcode= $rv[1] if !$rv[0];
106
    return if $errcode;
107
        #errorcode 5: should be private list
108
        #errorcode 8: should not be owner
109
110
    my $dbkey= keytostring( stringtokey($key, 0), 1);
111
    if( AcceptShare($shelfnumber, $dbkey, $loggedinuser) ) {
112
        #redirect to view of this shared list
113
        print $query->redirect("/cgi-bin/koha/opac-shelves.pl?display=privateshelves&viewshelf=$shelfnumber");
114
        exit;
115
    }
116
    else {
117
        $errcode= 7; #not accepted (key not found or expired)
118
    }
101
}
119
}
102
120
103
sub process_addrlist {
121
sub process_addrlist {
Lines 149-162 sub send_invitekey { Link Here
149
    }
167
    }
150
}
168
}
151
169
152
sub check_owner_category {
153
    #FIXME candidate for a module? what held me back is: getting back the two different error codes and the shelfname
154
    (undef,$shelfname,$owner,my $category)= GetShelf($shelfnumber);
155
    $errcode=4 if $owner!= $loggedinuser; #should be owner
156
    $errcode=5 if !$errcode && $category!=1; #should be private
157
    return $errcode==0;
158
}
159
160
sub load_template {
170
sub load_template {
161
    my ($file)= @_;
171
    my ($file)= @_;
162
    ($template, $loggedinuser, $cookie)= get_template_and_user({
172
    ($template, $loggedinuser, $cookie)= get_template_and_user({
Lines 208-214 sub stringtokey { Link Here
208
    for(my $i=0; $i<@temp-1; $i+=2) {
218
    for(my $i=0; $i<@temp-1; $i+=2) {
209
        push @retval, $temp[$i]*10+$temp[$i+1];
219
        push @retval, $temp[$i]*10+$temp[$i+1];
210
    }
220
    }
211
    return @retval;
221
    return \@retval;
212
}
222
}
213
223
214
sub base64ord { #base64 ordinal
224
sub base64ord { #base64 ordinal
215
- 

Return to bug 10389