@@ -, +, @@ --- C4/Output.pm | 19 +- C4/Utils/DataTables/VirtualShelves.pm | 7 +- C4/VirtualShelves/Page.pm | 19 -- Koha/Virtualshelf.pm | 56 +++ .../prog/en/includes/virtualshelves-toolbar.inc | 24 +- .../prog/en/modules/catalogue/detail.tt | 4 +- .../en/modules/virtualshelves/downloadshelf.tt | 16 + .../prog/en/modules/virtualshelves/shelves.tt | 375 ++++++++++----------- .../virtualshelves/tables/shelves_results.tt | 15 +- t/db_dependent/Virtualshelves.t | 107 +++++- virtualshelves/addbybiblionumber.pl | 7 +- virtualshelves/downloadshelf.pl | 69 ++-- virtualshelves/shelves.pl | 258 +++++++++++++- 13 files changed, 698 insertions(+), 278 deletions(-) --- a/C4/Output.pm +++ a/C4/Output.pm @@ -86,10 +86,12 @@ This function returns HTML, without any language dependency. =cut sub pagination_bar { - my $base_url = (@_ ? shift : $ENV{SCRIPT_NAME} . $ENV{QUERY_STRING}) or return; + my $base_url = (@_ ? shift : $ENV{SCRIPT_NAME} . $ENV{QUERY_STRING}); + return unless defined $base_url; my $nb_pages = (@_) ? shift : 1; my $current_page = (@_) ? shift : undef; # delay default until later my $startfrom_name = (@_) ? shift : 'page'; + my $additional_parameters = shift || {}; # how many pages to show before and after the current page? my $pages_around = 2; @@ -106,6 +108,10 @@ sub pagination_bar { $base_url =~ s/$delim$//; # remove trailing delim my $url = $base_url . (($base_url =~ m/$delim/ or $base_url =~ m/\?/) ? '&' : '?' ) . $startfrom_name . '='; + my $url_suffix; + while ( my ( $k, $v ) = each %$additional_parameters ) { + $url_suffix .= '&' . $k . '=' . $v; + } my $pagination_bar = ''; # navigation bar useful only if more than one page to display ! @@ -117,7 +123,9 @@ sub pagination_bar { "\n" . ' ' . '' + . '1' + . $url_suffix + . '"rel="start">' . '<<' . ''; } else { @@ -134,6 +142,7 @@ sub pagination_bar { . ''; } else { @@ -172,7 +181,9 @@ sub pagination_bar { "\n" . ' ' . '' + . $page_number + . $url_suffix + . '">' . $page_number . ''; } $last_displayed_page = $page_number; @@ -187,6 +198,7 @@ sub pagination_bar { . ' '; } else { @@ -200,6 +212,7 @@ sub pagination_bar { . ' ' . '>>' . ''; } --- a/C4/Utils/DataTables/VirtualShelves.pm +++ a/C4/Utils/DataTables/VirtualShelves.pm @@ -5,7 +5,7 @@ use C4::Branch qw/onlymine/; use C4::Context; use C4::Members qw/GetMemberIssuesAndFines/; use C4::Utils::DataTables; -use C4::VirtualShelves; +use Koha::Virtualshelves; sub search { my ( $params ) = @_; @@ -121,8 +121,9 @@ sub search { ( $iTotalRecords ) = $dbh->selectrow_array( $query, undef, @args ); for my $shelf ( @$shelves ) { - $shelf->{can_manage_shelf} = C4::VirtualShelves::ShelfPossibleAction( $loggedinuser, $shelf->{shelfnumber}, 'manage' ); - $shelf->{can_delete_shelf} = C4::VirtualShelves::ShelfPossibleAction( $loggedinuser, $shelf->{shelfnumber}, 'delete_shelf' ); + my $s = Koha::Virtualshelves->find( $shelf->{shelfnumber} ); + $shelf->{can_manage_shelf} = $s->can_be_managed( $loggedinuser ); + $shelf->{can_delete_shelf} = $s->can_be_deleted( $loggedinuser ); } return { iTotalRecords => $iTotalRecords, --- a/C4/VirtualShelves/Page.pm +++ a/C4/VirtualShelves/Page.pm @@ -68,7 +68,6 @@ sub shelfpage { loggedinuser => $loggedinuser, OpacAllowPublicListCreation => C4::Context->preference('OpacAllowPublicListCreation'), ); - my $edit; my $shelves; my @paramsloop; my $totitems; @@ -209,7 +208,6 @@ sub shelfpage { my $shelf = Koha::Virtualshelves->find( $shelfnumber ); my $member = GetMember( 'borrowernumber' => $shelf->owner ); my $ownername = defined($member) ? $member->{firstname} . " " . $member->{surname} : ''; - $edit = 1; $template->param( edit => 1, display => $displaymode, @@ -231,9 +229,6 @@ sub shelfpage { #View a shelf if ( $shelfnumber = $query->param('viewshelf') ) { my $shelf = Koha::Virtualshelves->find( $shelfnumber ); - $template->param( - 'DisplayMultiPlaceHold' => C4::Context->preference('DisplayMultiPlaceHold'), - ); if (C4::Context->preference('TagsEnabled')) { $template->param(TagsEnabled => 1); foreach (qw(TagsShowOnList TagsInputOnList)) { @@ -494,20 +489,6 @@ sub shelfpage { csv_profiles => GetCsvProfilesLoop('marc') ); - unless( $shelfnumber or $shelves or $edit ) { - # Only used for intranet - $template->param( op => 'list' ); - } - - if ($shelves or # note: this part looks duplicative, but is intentional - $edit - ) { - $template->param( seflag => 1 ); - #This hack is just another argument for refactoring this script one day - #At this point you are adding or editing a list; if you add, then you add a private list (by default) with permissions as below; if you edit, do not pass these permissions, they must come from the database - $template->param( allow_add => 0, allow_delete_own => 1, allow_delete_other => 0) unless $shelfnumber; - } - #Next call updates the shelves for the Lists button. #May not always be needed (when nothing changed), but doesn't take much. my ($total, $pubshelves, $barshelves) = C4::VirtualShelves::GetSomeShelfNames($loggedinuser, 'MASTHEAD'); --- a/Koha/Virtualshelf.pm +++ a/Koha/Virtualshelf.pm @@ -19,6 +19,9 @@ use Modern::Perl; use Carp; +use C4::Auth; + +use Koha::Borrowers; use Koha::Database; use Koha::DateUtils qw( dt_from_string ); use Koha::Exceptions; @@ -201,6 +204,59 @@ sub remove_biblios { return $number_removed; } +sub can_be_viewed { + my ( $self, $borrowernumber ) = @_; + return 1 if $self->category == $PUBLIC; + return 0 unless $borrowernumber; + return 1 if $self->owner == $borrowernumber; + return $self->get_shares->search( + { + borrowernumber => $borrowernumber, + } + )->count; +} + +sub can_be_deleted { + my ( $self, $borrowernumber ) = @_; + + return 0 unless $borrowernumber; + return 1 if $self->owner == $borrowernumber; + + my $patron = Koha::Borrowers->find( $borrowernumber ); + + return 1 if $self->category == $PUBLIC and C4::Auth::haspermission( $patron->userid, { lists => 'delete_public_lists' } ); + + return 0; +} + +sub can_be_managed { + my ( $self, $borrowernumber ) = @_; + return 1 + if $borrowernumber and $self->owner == $borrowernumber; + return 0; +} + +sub can_biblios_be_added { + my ( $self, $borrowernumber ) = @_; + + return 1 + if $borrowernumber + and ( $self->owner == $borrowernumber + or $self->allow_add ); + return 0; +} + +sub can_biblios_be_removed { + my ( $self, $borrowernumber ) = @_; + + return 1 + if $borrowernumber + and ( $self->owner == $borrowernumber + or $self->allow_delete_own + or $self->allow_delete_other ); + return 0; +} + sub type { return 'Virtualshelve'; } --- a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc +++ a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc @@ -1,7 +1,7 @@
-
New list
+
New list
- [% IF ( viewshelf ) %] - [% IF ( manageshelf ) %] + [% IF op == 'view' %] + [% IF can_manage_shelf %]
- +
[% END %] @@ -56,6 +52,6 @@
Send list
-
Print list
+
Print list
[% END %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -359,7 +359,7 @@ function verify_images() { [% IF ( GetShelves ) %] Lists that include this title: [% FOREACH GetShelve IN GetShelves %] - [% GetShelve.shelfname %] + [% GetShelve.shelfname %] [% IF ( loop.last ) %][% ELSE %]|[% END %] [% END %] @@ -524,7 +524,7 @@ function verify_images() {
  • Lists that include this title:
  • --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt @@ -3,6 +3,22 @@ [% INCLUDE 'doc-head-close.inc' %] + +[% FOR m IN messages %] +
    + [% SWITCH m.code %] + [% CASE 'unauthorized' %] + You do not have permission to view this list. + [% CASE 'does_not_exist' %] + This list does not exist. + [% CASE %] + [% m.code %] + [% END %] +
    +[% END %] + + + [% IF ( format ) %]

    Your download should begin automatically.

    [% ELSE %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt @@ -1,5 +1,9 @@ +[% USE Koha %] +[% USE KohaDates %] +[% SET PRIVATE = 1 %] +[% SET PUBLIC = 2 %] [% INCLUDE 'doc-head-open.inc' %] -Koha › [% IF ( viewshelf ) %]Lists › Contents of [% shelfname | html %][% ELSE %]Lists[% END %][% IF ( shelves ) %] › Create new list[% END %][% IF ( edit ) %] › Edit list [% shelfname | html %][% END %] +Koha › [% IF op == 'view' %]Lists › Contents of [% shelf.shelfname | html %][% ELSE %]Lists[% END %][% IF op == 'add_form' %] › Create new list[% END %][% IF op == 'edit_form' %] › Edit list [% shelf.shelfname | html %][% END %] [% INCLUDE 'doc-head-close.inc' %] [% INCLUDE 'datatables.inc' %] @@ -14,7 +18,7 @@ [% END %] -[% IF ( viewshelf ) %] +[% IF op == 'view' %] [% END %] @@ -27,7 +31,11 @@ var MSG_CONFIRM_DELETE_LIST = _("Are you sure you want to remove this list?"); [% IF op == 'list' %] $(document).ready(function(){ - var type = 1; + [% IF category == PUBLIC %] + var type = [% PUBLIC %]; + [% ELSE %] + var type = [% PRIVATE %]; + [% END %] var dtListResults = $("#listresultst").dataTable($.extend(true, {}, dataTablesDefaults, { 'bServerSide': true, 'sAjaxSource': "/cgi-bin/koha/svc/virtualshelves/search", @@ -81,13 +89,18 @@ $(document).ready(function(){ dtListResults.fnAddFilters("filter", 750); var tabs = $("#tabs").tabs({ + [% IF category == PUBLIC %] + active: 1, + [% ELSE %] + active: 0, + [% END %] activate: function(e, ui) { var active = tabs.tabs("option", "active" ); if ( active == 0 ) { - type = 1; // private + type = [% PRIVATE %]; dtListResults.fnDraw(); } else if ( active == 1 ) { - type = 2; // public + type = [% PUBLIC %]; dtListResults.fnDraw(); } } @@ -95,7 +108,7 @@ $(document).ready(function(){ }); [% END %] -[% IF ( viewshelf ) %] +[% IF op == 'view' %] $(document).ready(function(){ [% IF ( itemsloop ) %]$('#searchheader').fixFloat();[% END %] $("span.clearall").html(""+_("Clear all")+"<\/a>"); @@ -173,14 +186,6 @@ $(document).ready(function(){ }); [% END %] - function confirmDelete(message){ - if (window.confirm(message)) { - location.href="/cgi-bin/koha/virtualshelves/shelves.pl?[% IF ( showprivateshelves ) %]display=privateshelves&[% END %]shelves=1&DEL-[% shelfnumber %]=1&shelfoff=[% shelfoff %]"; - } else { - return false; - } - } - /** * This function checks if the adequate number of records are checked for merging */ @@ -272,35 +277,28 @@ function placeHold () { [% INCLUDE 'header.inc' %] [% INCLUDE 'cat-search.inc' %] -[% BLOCK list_permissions %] -
  • - - -  anyone else to add entries. -
  • -
  • - - -  anyone to remove his own contributed entries. -
  • -
  • - - -  anyone to remove other contributed entries. -
  • -[% END %] -
    @@ -318,70 +316,53 @@ function placeHold () { [% CASE 'error_on_insert' %] An error occurred when inserting this list. Perhaps the name already exists. [% CASE 'error_on_delete' %] - An error occurred when deleteing this list. Check the logs. + An error occurred when deleting this list. Check the logs. + [% CASE 'error_on_add_biblio' %] + The item has not been added to the list. Please check it's not in this list yet. [% CASE 'success_on_update' %] List updated with success. [% CASE 'success_on_insert' %] List inserted with success. [% CASE 'success_on_delete' %] List deleted with success. - [% CASE 'Koha::Exception::DuplicateObject' %] + [% CASE 'success_on_add_biblio' %] + The item has been added to the list. + [% CASE 'success_on_remove_biblios' %] + The item has been removed from the list. + [% CASE 'does_not_exist' %] + This list does not exist. + [% CASE 'item_does_not_exist' %] + This item does not exist. + [% CASE 'unauthorized_on_view' %] + You do not have permission to view this list. + [% CASE 'unauthorized_on_update' %] + You do not have permission to update this list. + [% CASE 'unauthorized_on_delete' %] + You do not have permission to delete this list. + [% CASE 'unauthorized_on_add_biblio' %] + You do not have permission to add a biblio to this list. + [% CASE 'no_biblio_removed' %] + No biblio has been removed. + [% CASE 'Koha::Exceptions::Virtualshelves::DuplicateObject' %] An error occurred when inserting this list. The name already [% shelfname %] exists. + [% CASE 'DBIx::Class::Exception' %] + [% m.msg %] [% CASE %] [% m.code %] [% END %]
    [% END %] -[% IF ( paramsloop ) %] -[% FOREACH paramsloo IN paramsloop %] -
    -
    - [% IF ( paramsloo.status ) %]
    [% paramsloo.string %]
    [% END %] - [% IF ( paramsloo.nobarcode ) %]
    ERROR: No barcode given.
    [% END %] - [% IF ( paramsloo.noshelfnumber ) %]
    ERROR: No list number given.
    [% END %] - [% IF ( paramsloo.need_confirm ) %] -
    The list [% paramsloo.need_confirm %] is not empty. - [% IF ( paramsloo.single ) %] -
    It has [% paramsloo.count %] entry. - [% ELSE %] -
    It has [% paramsloo.count %] entries. - [% END %] -
    Use the "Confirm" button below to confirm deletion. -
    - [% END %] - [% IF ( paramsloo.nopermission ) %] -
    ERROR: You do not have adequate permission for that action on list [% paramsloo.nopermission %].
    - [% END %] - [% IF ( paramsloo.failgetitem ) %] -
    ERROR: No item found with barcode [% paramsloo.failgetitem %].
    - [% END %] - [% IF ( paramsloo.duplicatebiblio ) %] -
    A record matching barcode [% paramsloo.duplicatebiblio %] has already been added.
    - [% END %] - [% IF ( paramsloo.nothingdeleted) %] -
    Warning: You could not delete any of the selected items from this list.
    - [% END %] - [% IF ( paramsloo.somedeleted) %] -
    Warning: You could not delete all selected items from this list.
    - [% END %] - [% IF ( paramsloo.modifyfailure) %] -
    ERROR: List could not be modified.
    - [% END %] -
    -
    -[% END %] -[% END %] - -[% IF ( viewshelf ) %] +[% IF op == 'view' %]
    - [% IF ( itemsloop ) %] + [% IF itemsloop %] -

    Contents of [% shelfname | html %]

    +

    Contents of [% shelf.shelfname | html %]

    [% pagination_bar %]
    - - + + + [% IF direction == 'asc' %] [% SET new_direction = 'desc' %] @@ -391,16 +372,16 @@ function placeHold () { [% END %]
    - [% IF ( itemsloop ) %] + [% IF itemsloop %]
    | |   - [% IF ( CAN_user_reserveforothers && DisplayMultiPlaceHold ) %] + [% IF CAN_user_reserveforothers && Koha.Preference('DisplayMultiPlaceHold') %]
    [% END %] - [% IF ( allowremovingitems ) %] + [% IF can_remove_biblios %]
    [% END %] [% IF ( CAN_user_editcatalogue_edit_catalogue ) %]
    [% END %] @@ -414,16 +395,16 @@ function placeHold () { [% UNLESS ( item_level_itypes ) %]Item type[% END %] - Title - [% IF sort == 'title' %] + Title + [% IF sortfield == 'title' %] [% direction %] sort [% ELSE %] [% END %] - Author - [% IF sort == 'author' %] + Author + [% IF sortfield == 'author' %] [% direction %] sort [% ELSE %] @@ -431,30 +412,25 @@ function placeHold () { Date added - Call number - [% IF sort == 'itemcallnumber' %] + Call number + [% IF sortfield == 'itemcallnumber' %] [% direction %] sort [% ELSE %] [% END %] - [% FOREACH itemsloo IN itemsloop %] - [% UNLESS ( loop.odd ) %] - - [% ELSE %] - - [% END %] - [% IF ( itemsloop ) %] - - [% IF ( itemsloo.confirm ) %] - - - [% ELSE %] - - [% END %] - - [% END %] + [% FOREACH itemsloo IN itemsloop %] + [% UNLESS ( loop.odd ) %] + + [% ELSE %] + + [% END %] + [% IF itemsloop %] + + + + [% END %] [% UNLESS ( item_level_itypes ) %] [% UNLESS ( noItemTypeImages || !itemsloo.imageurl ) %][% itemsloo.description %][% END %][% itemsloo.description %] [% END %] @@ -483,10 +459,10 @@ function placeHold () { | Edit items [% END %]

    - - [% itemsloo.author %] - [% itemsloo.dateadded %] - + + [% itemsloo.author %] + [% itemsloo.dateadded | $KohaDates%] +
      [% FOREACH result IN itemsloo.ITEM_RESULTS %]
    • [% result.holdingbranch %] [% IF ( result.location_intranet ) %] ([% result.location_intranet %]) [% END %] @@ -505,88 +481,111 @@ function placeHold () { [% END %]
    -[% END %] +[% END %] -[% IF ( debug ) %] - [% IF ( edit ) %]
    Edit is on ([% shelfname | html %])
    [% END %] - [% IF ( seflag ) %]
    seflag is on ([% seflag %])
    [% END %] +[% IF can_add_biblios %] +
    + +
    + Add an item to [% shelfname | html %] +
      +
    1. + + + + + + +
    2. +
    +
    + +
    [% END %] -[% IF ( seflag ) %] +[% IF op == 'add_form' OR op == 'edit_form' %]
    - [% IF ( shelves ) %] - Create a new list - + [% IF op == 'add_form' %] + Create a new list + + [% ELSE %] + Edit list [% shelf.shelfname | html %] + + [% END %] + +
      -
    1. +
    2. + Required -
    3. -
    4. Owner: [% loggedinusername %]
    5. -
    6. -
    7. -
    8. -
    9. - [% INCLUDE list_permissions %] -
    - [% END %] - - [% IF ( edit ) %] - Edit list [% shelfname | html %] - - - [% IF ( showprivateshelves ) %][% END %] - -
      -
    1. - Required -
    2. -
    3. [% IF ( owner ) %][% ownername %][% ELSE %][% loggedinusername %][% END %]
    4. -
    5. -
    6. -
    7. -
    8. - [% INCLUDE list_permissions %] -
    - [% END %] + +
  • + Owner: + [% IF op == 'add_form' %] + [% loggedinusername %]
  • + [% ELSE %] + [% IF owner %] + [% owner.firstname _ ' ' _ owner.surname %] + [% ELSE %] + [% loggedinusername %] + [% END %] + [% END %] + +
  • +
  • +
  • +
  • -
    + [% FOR permission IN ['allow_add', 'allow_delete_own', 'allow_delete_other'] %] +
  • + [% IF loop.first %] + + [% ELSE %] + + [% END %] + + [% SWITCH permission %] + [% CASE 'allow_add' %] anyone else to add entries. + [% CASE 'allow_delete_own' %] anyone to remove his own contributed entries. + [% CASE 'allow_delete_other' %] anyone to remove other contributed entries. + [% END %] +
  • + [% END %] + + -
    - [% IF ( showprivateshelves ) %] - Cancel - [% ELSE %] - [% IF ( display == "viewshelf" ) %] - Cancel +
    + + [% IF referer == 'view' %] + Cancel + [% ELSE %] + [% IF category == PUBLIC %] + Cancel [% ELSE %] - Cancel + Cancel [% END %] [% END %]
    @@ -601,7 +600,7 @@ function placeHold () {
    -[% END %] +[% END %] [% IF op == 'list' %]

    Lists

    --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/tables/shelves_results.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/tables/shelves_results.tt @@ -10,7 +10,7 @@ "dt_type": "[% data.type %]", "dt_shelfname": - "[% data.shelfname | html%]", + "[% data.shelfname | html%]", "dt_count": "[% data.count %] item(s)", "dt_owner": @@ -34,7 +34,8 @@ [%~ IF can_manage_shelf ~%] [%~ action_block = '' ~%] [%~ action_block = action_block _ '' ~%] - [%~ action_block = action_block _ '' ~%] + [%~ action_block = action_block _ '' ~%] + [%~ action_block = action_block _ '' ~%] [%~ action_block = action_block _ '' ~%] [%~ action_block = action_block _ '' ~%] [%~ END ~%] @@ -42,13 +43,9 @@ [%~ action_block = action_block _ '
    ' ~%] [%~ action_block = action_block _ '' ~%] [%~ action_block = action_block _ '' ~%] - [%~ action_block = action_block _ '' ~%] - [%~ action_block = action_block _ '' ~%] - [%~ IF type == 1 ~%] - [%~ action_block = action_block _ '' ~%] - [%~ ELSE ~%] - [%~ action_block = action_block _ '' ~%] - [%~ END ~%] + [%~ action_block = action_block _ '' ~%] + [%~ action_block = action_block _ '' ~%] + [%~ action_block = action_block _ '' ~%] [%~ action_block = action_block _ '' ~%] [%~ action_block = action_block _ '
    ' ~%] [%~ END ~%] --- a/t/db_dependent/Virtualshelves.t +++ a/t/db_dependent/Virtualshelves.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use Modern::Perl; -use Test::More tests => 3; +use Test::More tests => 4; use DateTime::Duration; use C4::Context; @@ -236,3 +236,108 @@ subtest 'Shelf content' => sub { $number_of_contents = Koha::Virtualshelfcontents->search->count; is( $number_of_contents, 1, 'The biblio should have been deleted to the shelf by the patron 2, even if it is not his own content (allow_delete_other=1)' ); }; + +subtest 'Shelf permissions' => sub { + + plan tests => 40; + my $patron1 = $builder->build( { source => 'Borrower', value => { flags => '2096766' } } ); # 2096766 is everything checked but not superlibrarian + my $patron2 = $builder->build( { source => 'Borrower', value => { flags => '1048190' } } ); # 1048190 is everything checked but not superlibrarian and delete_public_lists + my $biblio1 = $builder->build( { source => 'Biblio', } ); + my $biblio2 = $builder->build( { source => 'Biblio', } ); + my $biblio3 = $builder->build( { source => 'Biblio', } ); + my $biblio4 = $builder->build( { source => 'Biblio', } ); + + + my $public_shelf = Koha::Virtualshelf->new( + { shelfname => "my first shelf", + owner => $patron1->{borrowernumber}, + category => 2, + allow_add => 0, + allow_delete_own => 0, + allow_delete_other => 0, + } + )->store; + + is( $public_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view his public list' ); + is( $public_shelf->can_be_viewed( $patron2->{borrowernumber} ), 1, 'Public list should be viewed by someone else' ); + + is( $public_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete his list' ); + is( $public_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Public list should not be deleted by someone else' ); + + is( $public_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage his list' ); + is( $public_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Public list should not be managed by someone else' ); + + is( $public_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to his list' ); + is( $public_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (add) by someone else' ); + + is( $public_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to his list' ); + is( $public_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 0, 'Public list should not be modified (remove) by someone else' ); + + + $public_shelf->allow_add(1); + $public_shelf->allow_delete_own(1); + $public_shelf->allow_delete_other(1); + $public_shelf->store; + + is( $public_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view his public list' ); + is( $public_shelf->can_be_viewed( $patron2->{borrowernumber} ), 1, 'Public list should be viewed by someone else' ); + + is( $public_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete his list' ); + is( $public_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Public list should not be deleted by someone else' ); + + is( $public_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage his list' ); + is( $public_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Public list should not be managed by someone else' ); + + is( $public_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to his list' ); + is( $public_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 1, 'Public list should not be modified (add) by someone else' ); + + is( $public_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to his list' ); + is( $public_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 1, 'Public list should not be modified (remove) by someone else' ); + + + my $private_shelf = Koha::Virtualshelf->new( + { shelfname => "my first shelf", + owner => $patron1->{borrowernumber}, + category => 1, + allow_add => 0, + allow_delete_own => 0, + allow_delete_other => 0, + } + )->store; + + is( $private_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view his list' ); + is( $private_shelf->can_be_viewed( $patron2->{borrowernumber} ), 0, 'Private list should not be viewed by someone else' ); + + is( $private_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete his list' ); + is( $private_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Private list should not be deleted by someone else' ); + + is( $private_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage his list' ); + is( $private_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Private list should not be managed by someone else' ); + + is( $private_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to his list' ); + is( $private_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 0, 'Private list should not be modified (add) by someone else' ); + + is( $private_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to his list' ); + is( $private_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 0, 'Private list should not be modified (remove) by someone else' ); + + + $private_shelf->allow_add(1); + $private_shelf->allow_delete_own(1); + $private_shelf->allow_delete_other(1); + $private_shelf->store; + + is( $private_shelf->can_be_viewed( $patron1->{borrowernumber} ), 1, 'The owner should be able to view his list' ); + is( $private_shelf->can_be_viewed( $patron2->{borrowernumber} ), 0, 'Private list should not be viewed by someone else' ); + + is( $private_shelf->can_be_deleted( $patron1->{borrowernumber} ), 1, 'The owner should be able to delete his list' ); + is( $private_shelf->can_be_deleted( $patron2->{borrowernumber} ), 0, 'Private list should not be deleted by someone else' ); + + is( $private_shelf->can_be_managed( $patron1->{borrowernumber} ), 1, 'The owner should be able to manage his list' ); + is( $private_shelf->can_be_managed( $patron2->{borrowernumber} ), 0, 'Private list should not be managed by someone else' ); + + is( $private_shelf->can_biblios_be_added( $patron1->{borrowernumber} ), 1, 'The owner should be able to add biblios to his list' ); + is( $private_shelf->can_biblios_be_added( $patron2->{borrowernumber} ), 1, 'Private list could be modified (add) by someone else # individual check done later' ); + + is( $private_shelf->can_biblios_be_removed( $patron1->{borrowernumber} ), 1, 'The owner should be able to remove biblios to his list' ); + is( $private_shelf->can_biblios_be_removed( $patron2->{borrowernumber} ), 1, 'Private list could be modified (remove) by someone else # individual check done later' ); +}; --- a/virtualshelves/addbybiblionumber.pl +++ a/virtualshelves/addbybiblionumber.pl @@ -155,7 +155,8 @@ sub HandleNewVirtualShelf { } sub HandleShelfNumber { - if($authorized= ShelfPossibleAction($loggedinuser, $shelfnumber, 'add')) { + my $shelf = Koha::Virtualshelves->find( $shelfnumber ); + if($authorized = $shelf->can_biblios_be_added( $loggedinuser ) ) { AddBibliosToShelf($shelfnumber, @biblionumber); #Close this page and return print $query->header; @@ -167,9 +168,9 @@ sub HandleShelfNumber { } sub HandleSelectedShelf { - if($authorized= ShelfPossibleAction( $loggedinuser, $shelfnumber, 'add')){ + my $shelf = Koha::Virtualshelves->find( $shelfnumber ); + if($authorized = $shelf->can_biblios_be_added( $loggedinuser ) ) { #confirm adding to specific shelf - my $shelf = Koha::Virtualshelves->find( $shelfnumber ); $template->param( singleshelf => 1, shelfnumber => $shelf->shelfnumber, --- a/virtualshelves/downloadshelf.pl +++ a/virtualshelves/downloadshelf.pl @@ -31,10 +31,13 @@ use C4::VirtualShelves; use C4::Record; use C4::Ris; use C4::Csv; + +use Koha::Virtualshelves; + use utf8; my $query = new CGI; -my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( +my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( { template_name => "virtualshelves/downloadshelf.tt", query => $query, @@ -47,6 +50,7 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user ( my $shelfid = $query->param('shelfid'); my $format = $query->param('format'); my $dbh = C4::Context->dbh; +my @messages; if ($shelfid && $format) { @@ -54,41 +58,52 @@ if ($shelfid && $format) { my $marcflavour = C4::Context->preference('marcflavour'); my $output=''; - # CSV - if ($format =~ /^\d+$/) { - my @biblios; - foreach (@$items) { - push @biblios, $_->{biblionumber}; - } - $output = marc2csv(\@biblios, $format); - } - else { #Other formats - foreach my $biblio (@$items) { - my $biblionumber = $biblio->{biblionumber}; - my $record = GetMarcBiblio($biblionumber, 1); - if ($format eq 'iso2709') { - $output .= $record->as_usmarc(); - } - elsif ($format eq 'ris') { - $output .= marc2ris($record); + my $shelf = Koha::Virtualshelves->find($shelfid); + if ( $shelf ) { + if ( $shelf->can_be_viewed( $loggedinuser ) ) { + + # CSV + if ($format =~ /^\d+$/) { + my @biblios; + foreach (@$items) { + push @biblios, $_->{biblionumber}; + } + $output = marc2csv(\@biblios, $format); } - elsif ($format eq 'bibtex') { - $output .= marc2bibtex($record, $biblionumber); + else { #Other formats + foreach my $biblio (@$items) { + my $biblionumber = $biblio->{biblionumber}; + my $record = GetMarcBiblio($biblionumber, 1); + if ($format eq 'iso2709') { + $output .= $record->as_usmarc(); + } + elsif ($format eq 'ris') { + $output .= marc2ris($record); + } + elsif ($format eq 'bibtex') { + $output .= marc2bibtex($record, $biblionumber); + } + } } + print $query->header( + -type => 'application/octet-stream', + -'Content-Transfer-Encoding' => 'binary', + -attachment=>"shelf.$format"); + print $output; + exit; + } else { + push @messages, { type => 'error', code => 'unauthorized' }; } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; } # If it was a CSV export we change the format after the export so the file extension is fine $format = "csv" if ($format =~ m/^\d+$/); - - print $query->header( - -type => 'application/octet-stream', - -'Content-Transfer-Encoding' => 'binary', - -attachment=>"shelf.$format"); - print $output; } else { $template->param(csv_profiles => GetCsvProfilesLoop('marc')); $template->param(shelfid => $shelfid); - output_html_with_http_headers $query, $cookie, $template->output; } +$template->param( messages => \@messages ); +output_html_with_http_headers $query, $cookie, $template->output; --- a/virtualshelves/shelves.pl +++ a/virtualshelves/shelves.pl @@ -1,7 +1,6 @@ #!/usr/bin/perl -# -# Copyright 2000-2002 Katipo Communications +# Copyright 2015 Koha Team # # This file is part of Koha. # @@ -18,22 +17,263 @@ # You should have received a copy of the GNU General Public License # along with Koha; if not, see . -use strict; -use warnings; +use Modern::Perl; use CGI qw ( -utf8 ); -use C4::VirtualShelves::Page; +use C4::VirtualShelves; use C4::Auth; +use C4::Biblio; +use C4::Csv; +use C4::Koha; +use C4::Items; +use C4::Members; +use C4::Output; +use C4::XSLT; +use Koha::Virtualshelves; my $query = new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( - { - template_name => "virtualshelves/shelves.tt", + { template_name => "virtualshelves/shelves.tt", query => $query, type => "intranet", authnotrequired => 0, flagsrequired => { catalogue => 1 }, } ); -$template->param( print => $query->param('print') ); -shelfpage('intranet', $query, $template, $loggedinuser, $cookie); + +my $op = $query->param('op') || 'list'; +my $referer = $query->param('referer') || $op; +my $category = $query->param('category') || 1; +my ( $shelf, $shelfnumber, @messages ); + +if ( $op eq 'add_form' ) { + # Nothing to do +} elsif ( $op eq 'edit_form' ) { + $shelfnumber = $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + + if ( $shelf ) { + $category = $shelf->category; + my $patron = GetMember( 'borrowernumber' => $shelf->owner ); + $template->param( owner => $patron, ); + unless ( $shelf->can_be_managed( $loggedinuser ) ) { + push @messages, { type => 'error', code => 'unauthorized_on_update' }; + $op = 'list'; + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } +} elsif ( $op eq 'add' ) { + eval { + $shelf = Koha::Virtualshelf->new( + { shelfname => $query->param('shelfname'), + sortfield => $query->param('sortfield'), + category => $query->param('category'), + allow_add => $query->param('allow_add'), + allow_delete_own => $query->param('allow_delete_own'), + allow_delete_other => $query->param('allow_delete_other'), + owner => $query->param('owner'), + } + ); + $shelf->store; + $shelfnumber = $shelf->shelfnumber; + }; + if ($@) { + push @messages, { type => 'error', code => ref($@), msg => $@ }; + } elsif ( not $shelf ) { + push @messages, { type => 'error', code => 'error_on_insert' }; + } else { + push @messages, { type => 'message', code => 'success_on_insert' }; + $op = 'view'; + } +} elsif ( $op eq 'edit' ) { + $shelfnumber = $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + + if ( $shelf ) { + $op = $referer; + if ( $shelf->can_be_managed( $loggedinuser ) ) { + $shelf->shelfname( $query->param('shelfname') ); + $shelf->sortfield( $query->param('sortfield') ); + $shelf->allow_add( $query->param('allow_add') ); + $shelf->allow_delete_own( $query->param('allow_delete_own') ); + $shelf->allow_delete_other( $query->param('allow_delete_other') ); + $shelf->category( $query->param('category') ); + eval { $shelf->store }; + + if ($@) { + push @messages, { type => 'error', code => 'error_on_update' }; + $op = 'edit_form'; + } else { + push @messages, { type => 'message', code => 'success_on_update' }; + } + } else { + push @messages, { type => 'error', code => 'unauthorized_on_update' }; + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } +} elsif ( $op eq 'delete' ) { + $shelfnumber = $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + if ($shelf) { + if ( $shelf->can_be_deleted( $loggedinuser ) ) { + eval { $shelf->delete; }; + if ($@) { + push @messages, { type => 'error', code => ref($@), msg => $@ }; + } else { + push @messages, { type => 'message', code => 'success_on_delete' }; + } + } else { + push @messages, { type => 'error', code => 'unauthorized_on_delete' }; + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } + $op = 'list'; +} elsif ( $op eq 'add_biblio' ) { + $shelfnumber = $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + if ($shelf) { + if( my $barcode = $query->param('barcode') ) { + my $item = GetItem( 0, $barcode); + if (defined $item && $item->{itemnumber}) { + my $biblio = GetBiblioFromItemNumber( $item->{itemnumber} ); + if ( $shelf->can_biblios_be_added( $loggedinuser ) ) { + my $added = eval { $shelf->add_biblio( $biblio->{biblionumber}, $loggedinuser ); }; + if ($@) { + push @messages, { type => 'error', code => ref($@), msg => $@ }; + } elsif ( $added ) { + push @messages, { type => 'message', code => 'success_on_add_biblio' }; + } else { + push @messages, { type => 'message', code => 'error_on_add_biblio' }; + } + } else { + push @messages, { type => 'error', code => 'unauthorized_on_add_biblio' }; + } + } else { + push @messages, { type => 'error', code => 'item_does_not_exist' }; + } + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } + $op = $referer; +} elsif ( $op eq 'remove_biblios' ) { + $shelfnumber = $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + my @biblionumbers = $query->param('biblionumber'); + if ($shelf) { + if ( $shelf->can_biblios_be_removed( $loggedinuser ) ) { + my $number_of_biblios_removed = eval { + $shelf->remove_biblios( + { + biblionumbers => \@biblionumbers, + borrowernumber => $loggedinuser, + } + ); + }; + if ($@) { + push @messages, { type => 'error', code => ref($@), msg => $@ }; + } elsif ( $number_of_biblios_removed ) { + push @messages, { type => 'message', code => 'success_on_remove_biblios' }; + } else { + push @messages, { type => 'error', code => 'no_biblio_removed' }; + } + } else { + push @messages, { type => 'error', code => 'unauthorized_on_remove_biblios' }; + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } + $op = $referer; +} + +if ( $op eq 'view' ) { + $shelfnumber ||= $query->param('shelfnumber'); + $shelf = Koha::Virtualshelves->find($shelfnumber); + if ( $shelf ) { + if ( $shelf->can_be_viewed( $loggedinuser ) ) { + my $sortfield = $query->param('sortfield') || $shelf->sortfield; # Passed in sorting overrides default sorting + my $direction = $query->param('direction') || 'asc'; + my ( $shelflimit, $shelfoffset, $itemoff ); + unless ( $query->param('print') ) { + $shelflimit = C4::Context->preference('numSearchResults') || 20; + $itemoff = ( $query->param('itemoff') ? $query->param('itemoff') : 1 ); + $shelfoffset = ( $itemoff - 1 ) * $shelflimit; # Sets the offset to begin retrieving items at + } + my ( $items, $totitems ) = GetShelfContents( $shelfnumber, $shelflimit, $shelfoffset, $sortfield, $direction ); + + my $borrower = GetMember( borrowernumber => $loggedinuser ); + + for my $this_item (@$items) { + my $biblionumber = $this_item->{biblionumber}; + my $record = GetMarcBiblio($biblionumber); + + if ( C4::Context->preference("XSLTResultsDisplay") ) { + $this_item->{XSLTBloc} = XSLTParse4Display( $biblionumber, $record, "XSLTResultsDisplay" ); + } + + my $marcflavour = C4::Context->preference("marcflavour"); + $this_item->{'imageurl'} = getitemtypeinfo( $this_item->{'itemtype'}, 'intranet' )->{'imageurl'}; + $this_item->{'coins'} = GetCOinSBiblio($record); + $this_item->{'subtitle'} = GetRecordValue( 'subtitle', $record, GetFrameworkCode( $this_item->{'biblionumber'} ) ); + $this_item->{'normalized_upc'} = GetNormalizedUPC( $record, $marcflavour ); + $this_item->{'normalized_ean'} = GetNormalizedEAN( $record, $marcflavour ); + $this_item->{'normalized_oclc'} = GetNormalizedOCLCNumber( $record, $marcflavour ); + $this_item->{'normalized_isbn'} = GetNormalizedISBN( undef, $record, $marcflavour ); + + unless ( defined $this_item->{size} ) { + + #TT has problems with size + $this_item->{size} = q||; + } + + # Getting items infos for location display + my @items_infos = &GetItemsLocationInfo( $this_item->{'biblionumber'} ); + $this_item->{'ITEM_RESULTS'} = \@items_infos; + } + + # Build drop-down list for 'Add To:' menu... + my ( $totalref, $pubshelves, $barshelves ) = C4::VirtualShelves::GetSomeShelfNames( $loggedinuser, 'COMBO', 1 ); + $template->param( + addbarshelves => $totalref->{bartotal}, + addbarshelvesloop => $barshelves, + addpubshelves => $totalref->{pubtotal}, + addpubshelvesloop => $pubshelves, + can_manage_shelf => $shelf->can_be_managed($loggedinuser), + can_remove_shelf => $shelf->can_be_deleted($loggedinuser), + can_remove_biblios => $shelf->can_biblios_be_removed($loggedinuser), + can_add_biblios => $shelf->can_biblios_be_added($loggedinuser), + sortfield => $sortfield, + itemsloop => $items, + sortfield => $sortfield, + direction => $direction, + ); + if ($shelflimit) { + $template->param( + pagination_bar => pagination_bar( + q||, ( int( $totitems / $shelflimit ) ) + ( ( $totitems % $shelflimit ) > 0 ? 1 : 0 ), + $itemoff, "itemoff", { op => 'view', shelfnumber => $shelf->shelfnumber, sortfield => $sortfield, direction => $direction, } + ), + ); + } + } else { + push @messages, { type => 'error', code => 'unauthorized_on_view' }; + } + } else { + push @messages, { type => 'error', code => 'does_not_exist' }; + } +} + +$template->param( + op => $op, + referer => $referer, + shelf => $shelf, + messages => \@messages, + category => $category, + print => $query->param('print') || 0, + csv_profiles => GetCsvProfilesLoop('marc'), +); + +output_html_with_http_headers $query, $cookie, $template->output; --