Bug 31196: Remove 'default_value_for_mod_marc-' clear_from_cache calls
[koha.git] / t / db_dependent / Virtualshelves.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4 use Test::More tests => 7;
5 use DateTime::Duration;
6
7 use C4::Context;
8 use Koha::Database;
9 use Koha::DateUtils qw( dt_from_string );
10 use Koha::Virtualshelves;
11 use Koha::Virtualshelfshares;
12 use Koha::Virtualshelfcontents;
13
14 use t::lib::Dates;
15 use t::lib::TestBuilder;
16
17 my $builder = t::lib::TestBuilder->new;
18
19 my $schema = Koha::Database->new->schema;
20 $schema->storage->txn_begin;
21 my $dbh = C4::Context->dbh;
22 teardown();
23
24 subtest 'CRUD' => sub {
25     plan tests => 14;
26     my $patron = $builder->build({
27         source => 'Borrower',
28     });
29
30     my $number_of_shelves = Koha::Virtualshelves->search->count;
31
32     is( $number_of_shelves, 0, 'No shelves should exist' );
33
34     my $shelf = Koha::Virtualshelf->new({
35             shelfname => "my first shelf",
36             owner => $patron->{borrowernumber},
37             public => 0,
38         }
39     )->store;
40
41     is( ref( $shelf ), 'Koha::Virtualshelf', 'The constructor should return a valid object' );
42
43     $number_of_shelves = Koha::Virtualshelves->search->count;
44     is( $number_of_shelves, 1, '1 shelf should have been inserted' );
45     is( $shelf->allow_change_from_owner, 1, 'The default value for allow_change_from_owner should be 1' );
46     is( $shelf->allow_change_from_others, 0, 'The default value for allow_change_from_others should be 0' );
47     is ( $shelf->allow_change_from_staff, 0, 'The default value for allow_change_from_staff should be 0');
48     is( t::lib::Dates::compare( $shelf->created_on, dt_from_string), 0, 'The creation time should have been set to today' );
49
50     # Test if creation date will not be overwritten by store
51     my $created = dt_from_string->subtract( hours => 1 );
52     $shelf->created_on( $created );
53     $shelf->store;
54
55     my $retrieved_shelf = Koha::Virtualshelves->find( $shelf->shelfnumber );
56
57     is( $retrieved_shelf->shelfname, $shelf->shelfname, 'Find should correctly return the shelfname' );
58     is( t::lib::Dates::compare( $retrieved_shelf->created_on, $created), 0, 'Creation date is the same after update (Bug 18672)' );
59
60     # Insert with the same name
61     eval {
62         $shelf = Koha::Virtualshelf->new({
63                 shelfname => "my first shelf",
64                 owner => $patron->{borrowernumber},
65                 public => 0,
66             }
67         )->store;
68     };
69     is( ref($@), 'Koha::Exceptions::Virtualshelf::DuplicateObject',
70         'Exception on duplicate name' );
71     $number_of_shelves = Koha::Virtualshelves->search->count;
72     is( $number_of_shelves, 1, 'To be sure the number of shelves is still 1' );
73
74     my $another_patron = $builder->build({
75         source => 'Borrower',
76     });
77
78     $shelf = Koha::Virtualshelf->new({
79             shelfname => "my first shelf",
80             owner => $another_patron->{borrowernumber},
81             public => 0,
82         }
83     )->store;
84     $number_of_shelves = Koha::Virtualshelves->search->count;
85     is( $number_of_shelves, 2, 'Another patron should be able to create a shelf with an existing shelfname');
86
87     my $is_deleted = Koha::Virtualshelves->find( $shelf->shelfnumber )->delete;
88     ok( $is_deleted, 'The shelf has been deleted correctly' );
89     $number_of_shelves = Koha::Virtualshelves->search->count;
90     is( $number_of_shelves, 1, 'To be sure the shelf has been deleted' );
91
92     teardown();
93 };
94
95 subtest 'Sharing' => sub {
96     plan tests => 21;
97     my $patron_wants_to_share = $builder->build({
98         source => 'Borrower',
99     });
100     my $share_with_me = $builder->build({
101         source => 'Borrower',
102     });
103     my $just_another_patron = $builder->build({
104         source => 'Borrower',
105     });
106
107     my $number_of_shelves_shared = Koha::Virtualshelfshares->search->count;
108     is( $number_of_shelves_shared, 0, 'No shelves should exist' );
109
110     my $shelf_to_share = Koha::Virtualshelf->new({
111             shelfname => "my first shelf",
112             owner => $patron_wants_to_share->{borrowernumber},
113             public => 0,
114         }
115     )->store;
116
117     my $shelf_not_to_share = Koha::Virtualshelf->new({
118             shelfname => "my second shelf",
119             owner => $patron_wants_to_share->{borrowernumber},
120             public => 0,
121         }
122     )->store;
123
124     my $shared_shelf = eval { $shelf_to_share->share };
125     is ( ref( $@ ), 'Koha::Exceptions::Virtualshelf::InvalidKeyOnSharing', 'Do not share if no key given' );
126     $shared_shelf = eval { $shelf_to_share->share('valid key') };
127     is( ref( $shared_shelf ), 'Koha::Virtualshelfshare', 'On sharing, the method should return a valid Koha::Virtualshelfshare object' );
128
129     my $another_shared_shelf = eval { $shelf_to_share->share('valid key2') }; # Just to have 2 shares in DB
130
131     $number_of_shelves_shared = Koha::Virtualshelfshares->search->count;
132     is( $number_of_shelves_shared, 2, '2 shares should have been inserted' );
133
134     my $is_accepted = eval {
135         $shared_shelf->accept( 'invalid k', $share_with_me->{borrowernumber} );
136     };
137     is( $is_accepted, undef, 'The share should have not been accepted if the key is invalid' );
138     is( ref( $@ ), 'Koha::Exceptions::Virtualshelf::InvalidInviteKey', 'accept with an invalid key should raise an exception' );
139
140     $is_accepted = $shared_shelf->accept( 'valid key', $share_with_me->{borrowernumber} );
141     ok( defined($is_accepted), 'The share should have been accepted if the key valid' );
142
143     is( $shelf_to_share->is_shared, 1, 'first shelf is shared' );
144     is( $shelf_not_to_share->is_shared, 0, 'second shelf is not shared' );
145
146     is( $shelf_to_share->is_shared_with( $patron_wants_to_share->{borrowernumber} ), 0 , "The shelf should not be shared with the owner" );
147     is( $shelf_to_share->is_shared_with( $share_with_me->{borrowernumber} ), 1 , "The shelf should be shared with share_with_me" );
148     is( $shelf_to_share->is_shared_with( $just_another_patron->{borrowernumber} ), 0, "The shelf should not be shared with just_another_patron" );
149
150     is( $shelf_to_share->remove_share( $just_another_patron->{borrowernumber} ), 0, 'No share should be removed if the share has not been done with this patron' );
151     $number_of_shelves_shared = Koha::Virtualshelfshares->search->count;
152     is( $number_of_shelves_shared, 2, 'To be sure no shares have been removed' );
153
154     is( $shelf_not_to_share->remove_share( $share_with_me->{borrowernumber} ), 0, '0 share should have been removed if the shelf is not share' );
155     $number_of_shelves_shared = Koha::Virtualshelfshares->search->count;
156     is( $number_of_shelves_shared, 2, 'To be sure no shares have been removed' );
157
158     # Test double accept (BZ 11943) before removing the accepted share
159     my $third_share = $shelf_to_share->share('valid key3');
160     is( Koha::Virtualshelfshares->search->count, 3, 'Three shares' );
161     $is_accepted = $third_share->accept( 'valid key3', $share_with_me->{borrowernumber} );
162     is( $is_accepted->shelfnumber, $shelf_to_share->shelfnumber, 'Accept returned the existing share' );
163     is( Koha::Virtualshelfshares->search->count, 2, 'Check that number of shares went down again' );
164
165     # Remove the first accept
166     ok( $shelf_to_share->remove_share( $share_with_me->{borrowernumber} ), '1 share should have been removed if the shelf was shared with this patron' );
167     $number_of_shelves_shared = Koha::Virtualshelfshares->search->count;
168     is( $number_of_shelves_shared, 1, 'To be sure the share has been removed' );
169
170     teardown();
171 };
172
173 subtest 'Shelf content' => sub {
174
175     plan tests => 21;
176     my $patron1 = $builder->build( { source => 'Borrower', } );
177     my $patron2 = $builder->build( { source => 'Borrower', } );
178     my $patron3 = $builder->build( { source => 'Borrower', value => {flags => 1} });
179     my $biblio1 = $builder->build_sample_biblio;
180     my $biblio2 = $builder->build_sample_biblio;
181     my $biblio3 = $builder->build_sample_biblio;
182     my $biblio4 = $builder->build_sample_biblio;
183     my $number_of_contents = Koha::Virtualshelfcontents->search->count;
184
185     is( $number_of_contents, 0, 'No content should exist' );
186
187     my $dt_yesterday = dt_from_string->subtract_duration( DateTime::Duration->new( days => 1 ) );
188     my $shelf = Koha::Virtualshelf->new(
189         {   shelfname    => "my first shelf",
190             owner        => $patron1->{borrowernumber},
191             public       => 0,
192             lastmodified => $dt_yesterday,
193         }
194     )->store;
195
196     $shelf = Koha::Virtualshelves->find( $shelf->shelfnumber );
197     is( t::lib::Dates::compare( $shelf->lastmodified, $dt_yesterday), 0, 'The lastmodified has been set to yesterday, will be useful for another test later' );
198     my $content1 = $shelf->add_biblio( $biblio1->biblionumber, $patron1->{borrowernumber} );
199     is( ref($content1), 'Koha::Virtualshelfcontent', 'add_biblio to a shelf should return a Koha::Virtualshelfcontent object if inserted' );
200     $shelf = Koha::Virtualshelves->find( $shelf->shelfnumber );
201     is( t::lib::Dates::compare( $shelf->lastmodified, dt_from_string), 0, 'Adding a biblio to a shelf should update the lastmodified for the shelf' );
202     my $content2 = $shelf->add_biblio( $biblio2->biblionumber, $patron1->{borrowernumber} );
203     $number_of_contents = Koha::Virtualshelfcontents->search->count;
204     is( $number_of_contents, 2, '2 biblio should have been inserted' );
205
206     my $content1_bis = $shelf->add_biblio( $biblio1->biblionumber, $patron1->{borrowernumber} );
207     is( $content1_bis, undef, 'add_biblio should return undef on duplicate' );    # Or an exception ?
208     $number_of_contents = Koha::Virtualshelfcontents->search->count;
209     is( $number_of_contents, 2, 'The biblio should not have been duplicated' );
210
211     $shelf = Koha::Virtualshelves->find( $shelf->shelfnumber );
212     my $contents = $shelf->get_contents;
213     is( $contents->count, 2, 'There are 2 biblios on this shelf' );
214
215     # Patron 2 will try to remove biblios
216     # allow_change_from_owner = 1, allow_change_from_others = 0 (defaults)
217     my $number_of_deleted_biblios = $shelf->remove_biblios( { biblionumbers => [ $biblio1->biblionumber ], borrowernumber => $patron2->{borrowernumber} } );
218     is( $number_of_deleted_biblios, 0, 'Patron 2 removed nothing' );
219     # Now try with patron 1
220     $number_of_deleted_biblios = $shelf->remove_biblios( { biblionumbers => [ $biblio1->biblionumber ], borrowernumber => $patron1->{borrowernumber} } );
221     is( $number_of_deleted_biblios, 1, 'Patron 1 removed biblio' );
222     $number_of_contents = Koha::Virtualshelfcontents->search->count;
223     is( $number_of_contents, 1, 'To be sure the content has been deleted' );
224
225     # allow_change_from_owner == 0 (readonly)
226     $shelf->allow_change_from_owner( 0 );
227     $shelf->store;
228     $number_of_deleted_biblios = $shelf->remove_biblios( { biblionumbers => [ $biblio2->biblionumber ], borrowernumber => $patron1->{borrowernumber} } );
229     is( $number_of_deleted_biblios, 0, 'Owner could not delete' );
230     $number_of_contents = Koha::Virtualshelfcontents->search->count;
231     is( $number_of_contents, 1, 'Number of entries still equal to 1' );
232     $shelf->add_biblio( $biblio2->biblionumber, $patron1->{borrowernumber} );
233     $number_of_contents = Koha::Virtualshelfcontents->search->count;
234     is( $number_of_contents, 1, 'Biblio not added to the list' );
235     # Add back biblio1
236     $shelf->allow_change_from_owner( 1 );
237     $shelf->add_biblio( $biblio1->biblionumber, $patron1->{borrowernumber} );
238     $number_of_contents = Koha::Virtualshelfcontents->search->count;
239     is( $number_of_contents, 2, 'Biblio added to the list' );
240
241     # allow_change_from_others == 1
242     $shelf->allow_change_from_others( 1 );
243     my $content3 = $shelf->add_biblio( $biblio3->biblionumber, $patron2->{borrowernumber} );
244     my $content4 = $shelf->add_biblio( $biblio4->biblionumber, $patron2->{borrowernumber} );
245     $number_of_contents = Koha::Virtualshelfcontents->search->count;
246     is( $number_of_contents, 4, 'The biblio should have been added to the shelf by the patron 2' );
247     $number_of_deleted_biblios = $shelf->remove_biblios( { biblionumbers => [ $biblio3->biblionumber ], borrowernumber => $patron2->{borrowernumber} } );
248     is( $number_of_deleted_biblios, 1, 'Biblio 3 deleted by patron 2' );
249     $number_of_contents = Koha::Virtualshelfcontents->search->count;
250     is( $number_of_contents, 3, 'Back to three entries' );
251
252     # allow_change_from_staff == 1 and allow_change_from_others == 0
253     $shelf->allow_change_from_staff( 1 );
254     $shelf->allow_change_from_others( 0 );
255     $content4 = $shelf->add_biblio( $biblio3->biblionumber, $patron3->{borrowernumber} );
256     $number_of_contents = Koha::Virtualshelfcontents->search->count;
257     is( $number_of_contents, 4, 'The biblio should have been added to the shelf by patron 2');
258     $number_of_deleted_biblios = $shelf->remove_biblios( { biblionumbers => [ $biblio3->biblionumber ], borrowernumber => $patron3->{borrowernumber} } );
259     is( $number_of_deleted_biblios, 1, 'Biblio 3 deleted by patron 2' );
260     $number_of_contents = Koha::Virtualshelfcontents->search->count;
261     is( $number_of_contents, 3, 'Back to three entries' );
262
263     teardown();
264 };
265
266 subtest 'Shelf permissions' => sub {
267
268     plan tests => 100;
269     my $patron1 = $builder->build( { source => 'Borrower', value => { flags => '2096766' } } ); # 2096766 is everything checked but not superlibrarian
270     my $patron2 = $builder->build( { source => 'Borrower', value => { flags => '1048190' } } ); # 1048190 is everything checked but not superlibrarian and delete_public_lists
271     my $patron3 = $builder->build( { source => 'Borrower', value => { flags => '0' } } ); # this is a patron with no special permissions
272     my $patron4 = $builder->build( { source => 'Borrower', value => { flags => '0' } } );
273     my $sth = $dbh->prepare("INSERT INTO user_permissions (borrowernumber, module_bit, code) VALUES (?,?,?)");
274     $sth->execute($patron4->{borrowernumber}, 20, 'edit_public_lists'); # $patron4 only has the edit_public_lists sub-permission checked
275
276     my $biblio1 = $builder->build_sample_biblio;
277     my $biblio2 = $builder->build_sample_biblio;
278     my $biblio3 = $builder->build_sample_biblio;
279     my $biblio4 = $builder->build_sample_biblio;
280     my $biblio5 = $builder->build_sample_biblio;
281
282     my $public_shelf = Koha::Virtualshelf->new(
283         {   shelfname    => "my first shelf",
284             owner        => $patron1->{borrowernumber},
285             public       => 1,
286             allow_change_from_owner => 0,
287             allow_change_from_others => 0,
288             allow_change_from_staff => 0,
289         }
290     )->store;
291
292     is( $public_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view their public list' );
293     is( $public_shelf->can_be_viewed( $patron2->{borrowernumber} ), 1, 'Public list should be viewed by another staff member');
294     is( $public_shelf->can_be_viewed( $patron3->{borrowernumber} ), 1, 'Public list should be viewed by someone with no special permissions' );
295     is( $public_shelf->can_be_viewed( $patron4->{borrowernumber} ), 1, 'Public list should be viewed by someone with the edit_public_lists sub-permission checked' );
296
297     is( $public_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete their list' );
298     is( $public_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Public list should not be deleted by another staff member' );
299     is( $public_shelf->can_be_deleted( $patron3->{borrowernumber} ), 0, 'Public list should not be deleted by someone with no special permissions' );
300     is( $public_shelf->can_be_deleted( $patron4->{borrowernumber} ), 0, 'Public list should not be deleted by someone with the edit_public_lists sub-permission checked' );
301
302     is( $public_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage their list' );
303     is( $public_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Public list should not be managed by another staff member' );
304     is( $public_shelf->can_be_managed( $patron3->{borrowernumber} ), 0, 'Public list should not be managed by someone with no special permissions' );
305     is( $public_shelf->can_be_managed( $patron4->{borrowernumber} ), 1, 'Public list should be managed by someone with the edit_public_lists sub-permission checked' );
306
307     is( $public_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 0, 'The owner should not be able to add biblios to their list' );
308     is( $public_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (add) by another staff member' );
309     is( $public_shelf->can_biblios_be_added( $patron3->{borrowernumber} ), 0, 'Public list should not be modified (add) by someone with no special permissions' );
310     is( $public_shelf->can_biblios_be_added( $patron4->{borrowernumber} ), 0, 'Public list should not be modified (add) by someone with the edit_public_lists sub-permission checked' );
311
312     is( $public_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 0, 'The owner should not be able to remove biblios to their list' );
313     is( $public_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (remove) by another staff member' );
314     is ( $public_shelf->can_biblios_be_removed( $patron3->{borrowernumber} ), 0, 'Public list should not be modified (removed) by someone with no special permissions' );
315     is( $public_shelf->can_biblios_be_removed( $patron4->{borrowernumber} ), 0, 'Public list should not be modified (removed) by someone with the edit_public_lists sub-permission checked' );
316
317     $public_shelf->allow_change_from_owner(1);
318     $public_shelf->store;
319
320     is( $public_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view their public list' );
321     is( $public_shelf->can_be_viewed( $patron2->{borrowernumber} ), 1, 'Public list should be viewed by staff member' );
322     is( $public_shelf->can_be_viewed( $patron3->{borrowernumber} ), 1, 'Public list should be viewed by someone with no special permissions' );
323     is( $public_shelf->can_be_viewed( $patron4->{borrowernumber} ), 1, 'Public list should be viewable by someone with the edit_public_lists sub-permission checked' );
324
325     is( $public_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete their list' );
326     is( $public_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Public list should not be deleted by another staff member' );
327     is( $public_shelf->can_be_deleted( $patron3->{borrowernumber} ), 0, 'Public list should not be deleted by someone with no special permissions' );
328     is( $public_shelf->can_be_deleted( $patron4->{borrowernumber} ), 0, 'Public list should not be deleted by someone with the edit_public_lists sub-permission checked' );
329
330     is( $public_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage their list' );
331     is( $public_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Public list should not be managed by another staff member' );
332     is( $public_shelf->can_be_managed( $patron3->{borrowernumber} ), 0, 'Public list should not be managed by someone with no special permissions' );
333     is( $public_shelf->can_be_managed( $patron4->{borrowernumber} ), 1, 'Public list should be managed by someone with the edit_public_lists sub-permission checked' );
334
335     is( $public_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to their list' );
336     is( $public_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (add) by another staff member' );
337     is( $public_shelf->can_biblios_be_added( $patron3->{borrowernumber} ), 0, 'Public list should not be modified (add) by someone with no special permissions' );
338     is( $public_shelf->can_biblios_be_added( $patron4->{borrowernumber} ), 0, 'Public list should not be modified (add) by someone with the edit_public_lists sub-permission checked' );
339
340     is( $public_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to their list' );
341     is( $public_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (remove) by another staff member' );
342     is( $public_shelf->can_biblios_be_removed( $patron3->{borrowernumber} ), 0, 'Public list should not be modified (remove) by someone with no special permissions' );
343     is( $public_shelf->can_biblios_be_removed( $patron4->{borrowernumber} ), 0, 'Public list should not be modified (remove) by someone with the edit_public_list sub-permission checked' );
344
345     my $private_shelf = Koha::Virtualshelf->new(
346         {   shelfname    => "my first shelf",
347             owner        => $patron1->{borrowernumber},
348             public       => 0,
349             allow_change_from_owner => 0,
350             allow_change_from_others => 0,
351             allow_change_from_staff => 0,
352         }
353     )->store;
354
355     is( $private_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view their list' );
356     is( $private_shelf->can_be_viewed( $patron2->{borrowernumber} ), 0, 'Private list should not be viewed by another staff member' );
357     is( $private_shelf->can_be_viewed( $patron3->{borrowernumber} ), 0, 'Private list should not be viewed by someone with no special permissions' );
358     is( $private_shelf->can_be_viewed( $patron4->{borrowernumber} ), 0, 'Private list should not be viewed by someone with the edit_public_lists sub-permission checked' );
359
360     is( $private_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete their list' );
361     is( $private_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Private list should not be deleted by another staff member' );
362     is( $private_shelf->can_be_deleted( $patron3->{borrowernumber} ), 0, 'Private list should not be deleted by someone with no special permissions' );
363     is( $private_shelf->can_be_deleted( $patron4->{borrowernumber} ), 0, 'Private list should not be deleted by someone with the edit_public_lists sub-permission checked' );
364
365     is( $private_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage their list' );
366     is( $private_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Private list should not be managed by another staff member' );
367     is( $private_shelf->can_be_managed( $patron3->{borrowernumber} ), 0, 'Private list should not be managed by someone with no special permissions' );
368     is( $private_shelf->can_be_managed( $patron4->{borrowernumber} ), 0, 'Private list should not be managed by someone with the edit_public_lists sub-permission checked' );
369
370     is( $private_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 0, 'The owner should not be able to add biblios to their list' );
371     is( $private_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 0, 'Private list should not be modified (add) by another staff member' );
372     is( $private_shelf->can_biblios_be_added( $patron3->{borrowernumber} ), 0, 'Private list should not be modified (add) by someone with no special permissions' );
373     is( $private_shelf->can_biblios_be_added( $patron4->{borrowernumber} ), 0, 'Private list should not be modified (add) by someone with the edit_public_lists sub-permission checked' );
374
375     is( $private_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 0, 'The owner should not be able to remove biblios to their list' );
376     is( $private_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 0, 'Private list should not be modified (remove) by another staff member' );
377     is( $private_shelf->can_biblios_be_removed( $patron3->{borrowernumber} ), 0, 'Private list should not be modified (remove) by someone with no special permissions' );
378     is( $private_shelf->can_biblios_be_removed( $patron4->{borrowernumber} ), 0, 'Private list should not be modified (remove) by someone with the edit_public_lists sub-permissions' );
379
380     $private_shelf->allow_change_from_owner(1);
381     $private_shelf->allow_change_from_staff(1);
382     $private_shelf->allow_change_from_others(0);
383     $private_shelf->store;
384     is( $private_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view their list' );
385     is( $private_shelf->can_be_viewed( $patron2->{borrowernumber} ), 0, 'Private list should not be viewed by another staff member' );
386     is( $private_shelf->can_be_viewed( $patron3->{borrowernumber} ), 0, 'Private list should not be viewed by someone with no special permissions' );
387     is( $private_shelf->can_be_viewed( $patron4->{borrowernumber} ), 0, 'Private list should not be viewed by someone with the edit_public_lists sub-permission checked' );
388
389     is( $private_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete their list' );
390     is( $private_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Private list should not be deleted by another staff member' );
391     is( $private_shelf->can_be_deleted( $patron3->{borrowernumber} ), 0, 'Private list should not be deleted by someone with no special permissions' );
392     is( $private_shelf->can_be_deleted( $patron4->{borrowernumber} ), 0, 'Private list should not be deleted by someone with the edit_public_lists sub-permission checked' );
393
394     is( $private_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage their list' );
395     is( $private_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Private list should not be managed by another staff member' );
396     is( $private_shelf->can_be_managed( $patron3->{borrowernumber} ), 0, 'Private list should not be managed by someone with no special permissions' );
397     is( $private_shelf->can_be_managed( $patron4->{borrowernumber} ), 0, 'Private list should not be managed by someone with the edit_public_lists sub-permission checked' );
398
399     is( $private_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to their list' );
400     is( $private_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 1, 'Private list should not modified (add) by another staff member # individual check done later' );
401     is( $private_shelf->can_biblios_be_added( $patron3->{borrowernumber} ), 0, 'Private list should not be modified (add) by someone with no special permissions' );
402     is ( $private_shelf->can_biblios_be_added( $patron4->{borrowernumber} ), 0, 'Private list should not be modified (add) by someone with the edit_public_lists sub-permission checked' );
403
404     is( $private_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to their list' );
405     is( $private_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 1, 'Private list should be modified (remove) by another staff member # individual check done later' );
406     is( $private_shelf->can_biblios_be_removed( $patron3->{borrowernumber} ), 0, 'Private list should not be modified (remove) by someone with no special permissions' );
407     is( $private_shelf->can_biblios_be_removed( $patron4->{borrowernumber} ), 0, 'Private list should not be modified (remove) by someone with the edit_public_lists sub-permission checked' );
408
409     $private_shelf->allow_change_from_owner(1);
410     $private_shelf->allow_change_from_others(1);
411     $private_shelf->store;
412
413     is( $private_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view their list' );
414     is( $private_shelf->can_be_viewed( $patron2->{borrowernumber} ), 0, 'Private list should not be viewed by another staff member' );
415     is( $private_shelf->can_be_viewed( $patron3->{borrowernumber} ), 0, 'Private list should not be viewed by someone with no special permissions' );
416     is( $private_shelf->can_be_viewed( $patron4->{borrowernumber} ), 0, 'Private list should not be viewed by someone with the edit_public_lists sub-permission checked' );
417
418     is( $private_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete their list' );
419     is( $private_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Private list should not be deleted by another staff member' );
420     is( $private_shelf->can_be_deleted( $patron3->{borrowernumber} ), 0, 'Private list should not be deleted by someone with no special permissions' );
421     is( $private_shelf->can_be_deleted( $patron4->{borrowernumber} ), 0, 'Private list should not be deleted by someone with the edit_public_lists sub-permission checked' );
422
423     is( $private_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage their list' );
424     is( $private_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Private list should not be managed by another staff member' );
425     is( $private_shelf->can_be_managed( $patron3->{borrowernumber} ), 0, 'Private list should not be managed by someone with no special permissions' );
426     is( $private_shelf->can_be_managed( $patron4->{borrowernumber} ), 0, 'Private list should not be managed by someone with the edit_public_lists sub-permission checked' );
427
428     is( $private_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to their list' );
429     is( $private_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 1, 'Private list could be modified (add) by another staff member # individual check done later' );
430     is( $private_shelf->can_biblios_be_added( $patron3->{borrowernumber} ), 1, 'Private list could be modified (add) by someone with no special permissions' );
431     is( $private_shelf->can_biblios_be_added( $patron4->{borrowernumber} ), 1, 'Private list could be modified (add) by someone with the edit_public_lists sub-permission checked' );
432
433     is( $private_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to their list' );
434     is( $private_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 1, 'Private list could be modified (remove) by another staff member # individual check done later' );
435     is( $private_shelf->can_biblios_be_removed( $patron3->{borrowernumber} ), 1, 'Private list could be modified (remove) by someone with no special permissions' );
436     is( $private_shelf->can_biblios_be_removed( $patron4->{borrowernumber} ), 1, 'Private list could be modified (remove) by someone with the edit_public_lists sub-permission checked' );
437
438     teardown();
439 };
440
441 subtest 'Get shelves' => sub {
442     plan tests => 5;
443     my $patron1 = $builder->build({
444         source => 'Borrower',
445     });
446     my $patron2 = $builder->build({
447         source => 'Borrower',
448     });
449
450     my $private_shelf1_1 = Koha::Virtualshelf->new({
451             shelfname => "private shelf 1 for patron 1",
452             owner => $patron1->{borrowernumber},
453             public => 0,
454         }
455     )->store;
456     my $private_shelf1_2 = Koha::Virtualshelf->new({
457             shelfname => "private shelf 2 for patron 1",
458             owner => $patron1->{borrowernumber},
459             public => 0,
460         }
461     )->store;
462     my $private_shelf2_1 = Koha::Virtualshelf->new({
463             shelfname => "private shelf 1 for patron 2",
464             owner => $patron2->{borrowernumber},
465             public => 0,
466         }
467     )->store;
468     my $public_shelf1_1 = Koha::Virtualshelf->new({
469             shelfname => "public shelf 1 for patron 1",
470             owner => $patron1->{borrowernumber},
471             public => 1,
472         }
473     )->store;
474     my $public_shelf1_2 = Koha::Virtualshelf->new({
475             shelfname => "public shelf 2 for patron 1",
476             owner => $patron1->{borrowernumber},
477             public => 1,
478         }
479     )->store;
480     my $shelf_to_share = Koha::Virtualshelf->new({
481             shelfname => "shared shelf",
482             owner => $patron1->{borrowernumber},
483             public => 0,
484         }
485     )->store;
486
487     my $private_shelves = Koha::Virtualshelves->get_private_shelves;
488     is( $private_shelves->count, 0, 'Without borrowernumber given, get_private_shelves should not return any shelf' );
489     $private_shelves = Koha::Virtualshelves->get_private_shelves({ borrowernumber => $patron1->{borrowernumber} });
490     is( $private_shelves->count, 3, 'get_private_shelves should return all shelves for a given patron' );
491
492     $private_shelf2_1->share('a key')->accept('a key', $patron1->{borrowernumber});
493     $private_shelves = Koha::Virtualshelves->get_private_shelves({ borrowernumber => $patron1->{borrowernumber} });
494     is( $private_shelves->count, 4, 'get_private_shelves should return all shelves for a given patron, even the shared ones' );
495
496     my $public_shelves = Koha::Virtualshelves->get_public_shelves;
497     is( $public_shelves->count, 2, 'get_public_shelves should return all public shelves, no matter who is the owner' );
498
499     my $shared_shelf = eval { $shelf_to_share->share("valid key") };
500     my $shared_shelves = Koha::Virtualshelfshares->search({ borrowernumber => $patron1->{borrowernumber} });
501     is( $shared_shelves->count, 1, 'Found the share for patron1' );
502
503     teardown();
504 };
505
506 subtest 'Get shelves containing biblios' => sub {
507
508     plan tests => 9;
509     my $patron1 = $builder->build( { source => 'Borrower', } );
510     my $patron2 = $builder->build( { source => 'Borrower', } );
511     my $biblio1 = $builder->build_sample_biblio;
512     my $biblio2 = $builder->build_sample_biblio;
513     my $biblio3 = $builder->build_sample_biblio;
514     my $biblio4 = $builder->build_sample_biblio;
515
516     my $shelf1 = Koha::Virtualshelf->new(
517         {   shelfname    => "my first shelf",
518             owner        => $patron1->{borrowernumber},
519             public       => 0,
520         }
521     )->store;
522     my $shelf2 = Koha::Virtualshelf->new(
523         {   shelfname    => "my x second shelf", # 'x' to make it sorted after 'third'
524             owner        => $patron2->{borrowernumber},
525             public       => 0,
526         }
527     )->store;
528     my $shelf3 = Koha::Virtualshelf->new(
529         {   shelfname    => "my third shelf",
530             owner        => $patron1->{borrowernumber},
531             public       => 1,
532         }
533     )->store;
534
535     my $content1 = $shelf1->add_biblio( $biblio1->biblionumber, $patron1->{borrowernumber} );
536     my $content2 = $shelf1->add_biblio( $biblio2->biblionumber, $patron1->{borrowernumber} );
537     my $content3 = $shelf2->add_biblio( $biblio2->biblionumber, $patron2->{borrowernumber} );
538     my $content4 = $shelf2->add_biblio( $biblio3->biblionumber, $patron2->{borrowernumber} );
539     my $content5 = $shelf2->add_biblio( $biblio4->biblionumber, $patron2->{borrowernumber} );
540     my $content6 = $shelf3->add_biblio( $biblio4->biblionumber, $patron1->{borrowernumber} );
541
542     my $shelves_with_biblio1_for_any_patrons = Koha::Virtualshelves->get_shelves_containing_record(
543         {
544             biblionumber => $biblio1->biblionumber,
545         }
546     );
547     is ( $shelves_with_biblio1_for_any_patrons->count, 0, 'shelf1 is private and should not be displayed if patron is not logged in' );
548
549     my $shelves_with_biblio4_for_any_patrons = Koha::Virtualshelves->get_shelves_containing_record(
550         {
551             biblionumber => $biblio4->biblionumber,
552         }
553     );
554     is ( $shelves_with_biblio4_for_any_patrons->count, 1, 'shelf3 is public and should be displayed for any patrons' );
555     is ( $shelves_with_biblio4_for_any_patrons->next->shelfname, $shelf3->shelfname, 'The correct shelf (3) should be displayed' );
556
557     my $shelves_with_biblio1_for_other_patrons = Koha::Virtualshelves->get_shelves_containing_record(
558         {
559             biblionumber => $biblio1->biblionumber,
560             borrowernumber => $patron2->{borrowernumber},
561         }
562     );
563     is ( $shelves_with_biblio1_for_other_patrons->count, 0, 'shelf1 is private and should not be displayed for other patrons' );
564
565     my $shelves_with_biblio1_for_owner = Koha::Virtualshelves->get_shelves_containing_record(
566         {
567             biblionumber => $biblio1->biblionumber,
568             borrowernumber => $patron1->{borrowernumber},
569         }
570     );
571     is ( $shelves_with_biblio1_for_owner->count, 1, 'shelf1 is private and should be displayed for the owner' );
572
573     my $shelves_with_biblio2_for_patron1 = Koha::Virtualshelves->get_shelves_containing_record(
574         {
575             biblionumber => $biblio2->biblionumber,
576             borrowernumber => $patron1->{borrowernumber},
577         }
578     );
579     is ( $shelves_with_biblio2_for_patron1->count, 1, 'Only shelf1 should be displayed for patron 1 and biblio 1' );
580     is ( $shelves_with_biblio2_for_patron1->next->shelfname, $shelf1->shelfname, 'The correct shelf (1) should be displayed for patron 1' );
581
582     my $shelves_with_biblio4_for_patron2 = Koha::Virtualshelves->get_shelves_containing_record(
583         {
584             biblionumber => $biblio4->biblionumber,
585             borrowernumber => $patron2->{borrowernumber},
586         }
587     );
588     is ( $shelves_with_biblio4_for_patron2->count, 2, 'Patron should shown private and public lists for a given biblio' );
589     is ( $shelves_with_biblio4_for_patron2->next->shelfname, $shelf3->shelfname, 'The shelves should be sorted by shelfname' );
590
591     teardown();
592 };
593
594 subtest 'cannot_be_transferred' => sub {
595     plan tests => 12;
596
597     # Three patrons and a deleted one
598     my $staff = $builder->build_object({ class => 'Koha::Patrons', value => { flags => undef } });
599     my $listowner = $builder->build_object({ class => 'Koha::Patrons' });
600     my $receiver = $builder->build_object({ class => 'Koha::Patrons' });
601     my $removed_patron = $builder->build_object({ class => 'Koha::Patrons' });
602     $removed_patron->delete;
603
604     # Create three lists
605     my $private_list = Koha::Virtualshelf->new({ shelfname => "A", owner => $listowner->id })->store;
606     my $public_list = Koha::Virtualshelf->new({ shelfname => "B", public => 1, owner => $listowner->id })->store;
607     my $shared_list = Koha::Virtualshelf->new({ shelfname => "C", owner => $listowner->id })->store;
608     $shared_list->share("key")->accept( "key", $receiver->id );
609
610     # Test on private list
611     is( $private_list->cannot_be_transferred, 'unauthorized_transfer', 'Private list can never be transferred' );
612
613     # Test on public list
614     is( $public_list->cannot_be_transferred, 'missing_by_parameter', 'Public list, no parameters' );
615     is( $public_list->cannot_be_transferred({ by => $staff->id, to => $receiver->id }), 'unauthorized_transfer', 'Lacks permission' );
616     my $perms = $builder->build({ source => 'UserPermission', value  => {
617         borrowernumber => $staff->id, module_bit => 20, code => 'edit_public_lists',
618     }});
619     is( $public_list->cannot_be_transferred({ by => $staff->id, to => $receiver->id }), 0, 'Minimum permission passes' );
620     $staff->flags(1)->store;
621     is( $public_list->cannot_be_transferred({ by => $staff->id, to => $receiver->id }), 0, 'Superlibrarian permission passes' );
622     is( $public_list->cannot_be_transferred({ by => $staff->id, to => $receiver->id, interface => 'opac' }), 'unauthorized_transfer',
623         'Not supported on OPAC' );
624     is( $public_list->cannot_be_transferred({ by => $staff->id, to => $removed_patron->id }), 'new_owner_not_found', 'Removed patron cannot own' );
625
626     # Test on shared list
627     is( $shared_list->cannot_be_transferred({ by => $staff->id }), 'unauthorized_transfer', 'Shared list, transfer limited to owner' );
628     is( $shared_list->cannot_be_transferred({ by => $receiver->id }), 'unauthorized_transfer', 'Shared list, transfer still limited to owner' );
629     is( $shared_list->cannot_be_transferred({ by => $listowner->id, to => $receiver->id }), 0, 'sharee could become owner' );
630     is( $shared_list->cannot_be_transferred({ by => $listowner->id, to => $receiver->id, interface => 'intranet' }), 'unauthorized_transfer',
631         'Intranet not supported' );
632     is( $shared_list->cannot_be_transferred({ by => $listowner->id, to => $staff->id }), 'new_owner_has_no_share', 'staff has no share' );
633 };
634
635 $schema->storage->txn_rollback;
636
637 sub teardown {
638     $dbh->do(q|DELETE FROM virtualshelfshares|);
639     $dbh->do(q|DELETE FROM virtualshelfcontents|);
640     $dbh->do(q|DELETE FROM virtualshelves|);
641 }