@@ -, +, @@
---
.../prog/en/includes/html_helpers.inc | 12 +-
.../prog/en/modules/tools/batchMod-edit.tt | 20 +-
tools/batchMod.pl | 278 ++++++++++--------
3 files changed, 176 insertions(+), 134 deletions(-)
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc
+++ a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers.inc
@@ -116,7 +116,9 @@
[% ELSE %]
...
[% END %]
- [%- mv.javascript | $raw -%]
+ [% UNLESS no_plugin %][%# FIXME - from batchMod-edit, jQuery is included at the end of the template and cataloguing plugins are not working in this situation %]
+ [%- mv.javascript | $raw -%]
+ [% END %]
[% END %]
[% ELSIF ( mv.type == 'text' ) %]
[% IF mv.readonly %]
@@ -142,9 +144,9 @@
[% IF add_regex %]
- s/ /
- /
-
+ s/ /
+ /
+
[% END %]
@@ -162,7 +164,7 @@
[% IF add_regex %]
[% IF (mv.type == 'text' || mv.type == 'text2' || mv.type == 'textarea' ) %]
- RegEx
+ RegEx
[% END %]
[% END %]
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt
+++ a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchMod-edit.tt
@@ -248,7 +248,8 @@
Edit items
Checking the box right next to the subfield label will disable the entry and delete the subfield on all selected items. Leave fields blank to make no change.
- [% PROCESS subfields_for_item subfields => subfields, add_regex => 1, add_delete_checkbox => 1 %]
+ [%# no_plugin from batchMod-edit, jQuery is included at the end of the template and cataloguing plugins are not working in this situation %]
+ [% PROCESS subfields_for_item subfields => subfields, add_regex => 1, add_delete_checkbox => 1, no_plugin => 1 %]
@@ -310,8 +311,8 @@
$("input[name='disable_input']").click(function() {
var row = $(this).attr("id");
row = row.replace("row","hint");
- var todisable = $(this).parent().find("[name='field_value'],[name='tag'],[name='subfield'],[name='mandatory']");
- var regex_link = $(this).parent().find("[name='field_regex']");
+ var todisable = $(this).parent().find(".input_marceditor,.tag,.subfield,.mandatory");
+ var regex_link = $(this).parent().find(".field_regex");
if ($(this).is(":checked")) {
$(todisable).prop('disabled', true);
$("#"+row).html(_("This subfield will be deleted"));
@@ -322,12 +323,11 @@
$(regex_link).show();
}
});
- $('a[name="field_regex"]').click(function() {
- var id = $(this).attr('id');
- var editor = $(this).parent().find("[name='field_value']");
+ $('a.field_regex').click(function() {
+ var editor = $(this).parent().find(".input_marceditor");
var tag_editor = $(this).parent().find(".buttonDot");
var regex = $(this).parent().find("[name='regex_fields']");
- var disable_input = $(this).parent().find("[name='disable_input']");
+ var disable_input = $(this).parent().find(".disable_input");
if ($(this).html() == 'RegEx') {
$(editor).hide();
$(regex).show();
@@ -348,10 +348,10 @@
[% IF ( show ) %]
[%- # Loop over fields which may have plugin JavaScript -%]
[%- UNLESS (too_many_items_process) -%]
- [%- FOREACH ite IN item -%]
- [% SET mv = ite.marc_value %]
+ [%- FOREACH subfield IN subfields -%]
+ [% SET mv = subfield.marc_value %]
[%- IF ( mv.type == 'text2' ) -%]
-
+
[% mv.javascript | $raw %]
[%- END -%]
[%- END -%]
--- a/tools/batchMod.pl
+++ a/tools/batchMod.pl
@@ -117,51 +117,24 @@ if ($op eq "action") {
my @searches = $input->multi_param('regex_search');
my @replaces = $input->multi_param('regex_replace');
my @modifiers = $input->multi_param('regex_modifiers');
- my @disabled = $input->multi_param('disable_input');
+ my @subfields_to_blank = $input->multi_param('disable_input');
# build indicator hash.
my @ind_tag = $input->multi_param('ind_tag');
my @indicator = $input->multi_param('indicator');
- # Is there something to modify ?
- # TODO : We shall use this var to warn the user in case no modification was done to the items
- my $values_to_modify = scalar(grep {!/^$/} @values) || scalar(grep {!/^$/} @searches);
- my $values_to_blank = scalar(@disabled);
-
- my $marcitem;
-
- #initializing values for updates
- my ( $itemtagfield, $itemtagsubfield) = &GetMarcFromKohaField( "items.itemnumber" );
- if ($values_to_modify){
- my $xml = TransformHtmlToXml(\@tags,\@subfields,\@values,\@indicator,\@ind_tag, 'ITEM');
- $marcitem = MARC::Record::new_from_xml($xml, 'UTF-8');
- }
- if ($values_to_blank){
- foreach my $disabledsubf (@disabled){
- if ($marcitem && $marcitem->field($itemtagfield)){
- $marcitem->field($itemtagfield)->update( $disabledsubf => "" );
- }
- else {
- $marcitem = MARC::Record->new();
- $marcitem->append_fields( MARC::Field->new( $itemtagfield, '', '', $disabledsubf => "" ) );
- }
- }
- }
-
my $upd_biblionumbers;
my $del_biblionumbers;
- try {
- my $schema = Koha::Database->new->schema;
- $schema->txn_do(
- sub {
- # For each item
- my $i = 1;
- foreach my $itemnumber (@itemnumbers) {
- my $item = Koha::Items->find($itemnumber);
- next
- unless $item
- ; # Should have been tested earlier, but just in case...
- my $itemdata = $item->unblessed;
- if ($del) {
+ if ( $del ) {
+ try {
+ my $schema = Koha::Database->new->schema;
+ $schema->txn_do(
+ sub {
+ foreach my $itemnumber (@itemnumbers) {
+ my $item = Koha::Items->find($itemnumber);
+ next
+ unless $item
+ ; # Should have been tested earlier, but just in case...
+ my $itemdata = $item->unblessed;
my $return = $item->safe_delete;
if ( ref( $return ) ) {
$deleted_items++;
@@ -195,100 +168,137 @@ if ($op eq "action") {
}
}
}
- else {
- my $modified_holds_priority = 0;
- if ( defined $exclude_from_local_holds_priority && $exclude_from_local_holds_priority ne "" ) {
- if(!defined $item->exclude_from_local_holds_priority || $item->exclude_from_local_holds_priority != $exclude_from_local_holds_priority) {
- $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store;
- $modified_holds_priority = 1;
- }
- }
- my $modified = 0;
- if ( $values_to_modify || $values_to_blank ) {
- my $localmarcitem = Item2Marc($itemdata);
+ if (@not_deleted) {
+ Koha::Exceptions::Exception->throw(
+ 'Some items have not been deleted, rolling back');
+ }
+ }
+ );
+ }
+ catch {
+ warn $_;
+ if ( $_->isa('Koha::Exceptions::Exception') ) {
+ $template->param( deletion_failed => 1 );
+ }
+ die "Something terrible has happened!"
+ if ($_ =~ /Rollback failed/); # Rollback failed
+ };
+ }
- for ( my $i = 0 ; $i < @tags ; $i++ ) {
- my $search = $searches[$i];
- next unless $search;
+ else { # modification
- my $tag = $tags[$i];
- my $subfield = $subfields[$i];
- my $replace = $replaces[$i];
+ my @columns = Koha::Items->columns;
- my $value = $localmarcitem->field( $tag )->subfield( $subfield );
- my $old_value = $value;
+ my $new_item_data;
+ my @columns_with_regex;
+ for my $c ( @columns ) {
+ if ( $c eq 'more_subfields_xml' ) {
+ my @more_subfields_xml = $input->multi_param("items.more_subfields_xml");
+ my @unlinked_item_subfields;
+ for my $subfield ( @more_subfields_xml ) {
+ my $v = $input->param('items.more_subfields_xml_' . $subfield);
+ push @unlinked_item_subfields, $subfield, $v;
+ }
+ if ( @unlinked_item_subfields ) {
+ my $marc = MARC::Record->new();
+ # use of tag 999 is arbitrary, and doesn't need to match the item tag
+ # used in the framework
+ $marc->append_fields(MARC::Field->new('999', ' ', ' ', @unlinked_item_subfields));
+ $marc->encoding("UTF-8");
+ # FIXME This is WRONG! We need to use the values that haven't been modified by the batch tool!
+ $new_item_data->{more_subfields_xml} = $marc->as_xml("USMARC");
+ next;
+ }
+ $new_item_data->{more_subfields_xml} = undef;
+ # FIXME deal with more_subfields_xml and @subfields_to_blank
+ } elsif ( grep { $c eq $_ } @subfields_to_blank ) {
+ # Empty this column
+ $new_item_data->{$c} = undef
+ } else {
- my @available_modifiers = qw( i g );
- my $retained_modifiers = q||;
- for my $modifier ( split //, $modifiers[$i] ) {
- $retained_modifiers .= $modifier
- if grep {/$modifier/} @available_modifiers;
- }
- if ( $retained_modifiers =~ m/^(ig|gi)$/ ) {
- $value =~ s/$search/$replace/ig;
- }
- elsif ( $retained_modifiers eq 'i' ) {
- $value =~ s/$search/$replace/i;
- }
- elsif ( $retained_modifiers eq 'g' ) {
- $value =~ s/$search/$replace/g;
- }
- else {
- $value =~ s/$search/$replace/;
- }
+ my @v = grep { $_ ne "" }
+ uniq $input->multi_param( "items." . $c );
- my @fields_to = $localmarcitem->field($tag);
- foreach my $field_to_update ( @fields_to ) {
- unless ( $old_value eq $value ) {
- $modified++;
- $field_to_update->update( $subfield => $value );
- }
- }
+ next unless @v;
+
+ $new_item_data->{$c} = join ' | ', @v;
+ }
+
+ if ( my $regex_search = $input->param('items.'.$c.'_regex_search') ) {
+ push @columns_with_regex, $c;
+ }
+ }
+
+ try {
+ my $schema = Koha::Database->new->schema;
+ $schema->txn_do(
+ sub {
+
+ foreach my $itemnumber (@itemnumbers) {
+ my $item = Koha::Items->find($itemnumber);
+ next
+ unless $item
+ ; # Should have been tested earlier, but just in case...
+ my $itemdata = $item->unblessed;
+
+ my $modified_holds_priority = 0;
+ if ( defined $exclude_from_local_holds_priority && $exclude_from_local_holds_priority ne "" ) {
+ if(!defined $item->exclude_from_local_holds_priority || $item->exclude_from_local_holds_priority != $exclude_from_local_holds_priority) {
+ $item->exclude_from_local_holds_priority($exclude_from_local_holds_priority)->store;
+ $modified_holds_priority = 1;
}
+ }
- $modified += UpdateMarcWith( $marcitem, $localmarcitem );
- if ($modified) {
- eval {
- if (
- my $item = ModItemFromMarc(
- $localmarcitem,
- $itemdata->{biblionumber},
- $itemnumber,
- { skip_record_index => 1 },
- )
- )
- {
- LostItem(
- $itemnumber,
- 'batchmod',
- undef,
- { skip_record_index => 1 }
- ) if $item->{itemlost}
- and not $itemdata->{itemlost};
- }
- };
- push @$upd_biblionumbers, $itemdata->{'biblionumber'};
+ my $modified = 0;
+ for my $c ( @columns_with_regex ) {
+ my $regex_search = $input->param('items.'.$c.'_regex_search');
+ my $old_value = $item->$c;
+
+ my $value = apply_regex(
+ {
+ search => $regex_search,
+ replace => $input->param(
+ 'items' . $c . '_regex_replace'
+ ),
+ modifiers => $input->param(
+ 'items' . $c . '_regex_modifiers'
+ ),
+ value => $old_value,
+ }
+ );
+ unless ( $old_value eq $value ) {
+ $modified++;
+ $item->$c($value);
}
}
+
+ $modified += scalar(keys %$new_item_data); # FIXME This is incorrect if old value == new value. Should we loop of the keys and compare the before/after values?
+ if ( $modified) {
+ my $itemlost_pre = $item->itemlost;
+ $item->set($new_item_data)->store({skip_record_index => 1});
+
+ push @$upd_biblionumbers, $itemdata->{'biblionumber'};
+
+ LostItem(
+ $item->itemnumber, 'batchmod', undef,
+ { skip_record_index => 1 }
+ ) if $item->itemlost
+ and not $itemlost_pre;
+ }
+
$modified_items++ if $modified || $modified_holds_priority;
$modified_fields += $modified + $modified_holds_priority;
}
- $i++;
- }
- if (@not_deleted) {
- Koha::Exceptions::Exception->throw(
- 'Some items have not been deleted, rolling back');
}
- }
- );
- }
- catch {
- if ( $_->isa('Koha::Exceptions::Exception') ) {
- $template->param( deletion_failed => 1 );
+ );
}
- die "Something terrible has happened!"
- if ($_ =~ /Rollback failed/); # Rollback failed
- };
+ catch {
+ warn $_;
+ die "Something terrible has happened!"
+ if ($_ =~ /Rollback failed/); # Rollback failed
+ };
+ }
+
$upd_biblionumbers = [ uniq @$upd_biblionumbers ]; # Only update each bib once
# Don't send specialUpdate for records we are going to delete
@@ -323,6 +333,7 @@ if ($op eq "action") {
$template->param( "job_completed" => 1 );
}
+
# Calling the template
$template->param(
modified_items => $modified_items,
@@ -588,3 +599,32 @@ sub UpdateMarcWith {
}
return $modified;
}
+
+sub apply_regex {
+ my ($params) = @_;
+ my $search = $params->{search};
+ my $replace = $params->{replace};
+ my $modifiers = $params->{modifiers} || [];
+ my $value = $params->{value};
+
+ my @available_modifiers = qw( i g );
+ my $retained_modifiers = q||;
+ for my $modifier ( split //, @$modifiers ) {
+ $retained_modifiers .= $modifier
+ if grep { /$modifier/ } @available_modifiers;
+ }
+ if ( $retained_modifiers =~ m/^(ig|gi)$/ ) {
+ $value =~ s/$search/$replace/ig;
+ }
+ elsif ( $retained_modifiers eq 'i' ) {
+ $value =~ s/$search/$replace/i;
+ }
+ elsif ( $retained_modifiers eq 'g' ) {
+ $value =~ s/$search/$replace/g;
+ }
+ else {
+ $value =~ s/$search/$replace/;
+ }
+
+ return $value;
+}
--