From a2d7f48bcca61c09a45a7337ee5c00b93bcbd863 Mon Sep 17 00:00:00 2001
From: Paul Poulain <paul.poulain@biblibre.com>
Date: Mon, 25 Jul 2011 10:54:34 +0200
Subject: [PATCH] Bug 5725 : Batch Modifications for Biblios

commit 66282fed94564969f0368e27c7231116a2d1c0fe
Author: Chris Cormack <chrisc@catalyst.net.nz>
Date:   Tue Feb 22 08:43:24 2011 +1300

    Bug 5725 : Follow up fixing permissions thanks to Paul Poulain

commit 4d0241aea5be13b00abbc6100dc98ec87f816081
Author: Paul Poulain <paul.poulain@biblibre.com>
Date:   Mon Jan 10 17:22:31 2011 +0100

    Bug 5725 follow up

    Owen noticed the batchedit was not working. This was because we made a patch months ago to change the GetBiblio API
    (the 1st returned arg is useless)
    This patch is not in main trunk, resulting in the error owen has noticed.

    This patch goes back to official API (even if it is clumsy : the patch we did does not apply anymore)

commit 19b3e0ecc57af1c2151340328bf06e26882b7863
Author: Paul Poulain <paul.poulain@biblibre.com>
Date:   Wed Dec 15 20:47:21 2010 +0100

    Bug 5725 : MT #2991 (Feature) Batch biblio modifications

    This patch add a new feature of batch biblio modifications,
    it permit to select biblios from basket, and modify fields of them setting

    Rebased to fix whitespace issues.

Bug 5725 follow-up Fixes adresses comments 28 and 29 (from Owen)

* add a link to tools-home
* display the biblios before defining rules
* add some help/change some wording
* fixes result "Status" column (was a H:T:P => T:T glitch) and put the message on the top

I also removed an unused variable

Bug 5725 follow-upd, deal with leader

As Owen comment 33 notices, leader update was not working. This patch fixes the problem (and fix a few reindenting glitches as well)

Additional fixes for Bug 5725 - Batch modifications for Biblios

- Correcting page title
- Adding breadcrums
- Adding sidebar menu (matching other batch mod pages)
- Showing "loading" graphic during AJAX operations
- Adding empty option to list of MARC tags so that onchange event
  will fire when the user is choosing 000
- Other structural markup changes
---
 C4/Biblio.pm                                       |  101 ++++++++
 installer/data/mysql/updatedatabase.pl             |    8 +-
 koha-tmpl/intranet-tmpl/prog/en/js/basket.js       |    6 +
 .../intranet-tmpl/prog/en/modules/basket/basket.tt |    7 +
 .../prog/en/modules/tools/batchedit.tt             |  257 ++++++++++++++++++++
 .../prog/en/modules/tools/tools-home.tt            |    5 +
 koha-tmpl/intranet-tmpl/prog/img/loading-small.gif |  Bin 0 -> 1652 bytes
 tools/batchedit.pl                                 |  221 +++++++++++++++++
 8 files changed, 604 insertions(+), 1 deletions(-)
 create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchedit.tt
 create mode 100644 koha-tmpl/intranet-tmpl/prog/img/loading-small.gif
 create mode 100755 tools/batchedit.pl

diff --git a/C4/Biblio.pm b/C4/Biblio.pm
index 96baaef..ee83caf 100644
--- a/C4/Biblio.pm
+++ b/C4/Biblio.pm
@@ -128,6 +128,7 @@ BEGIN {
       &TransformHtmlToXml
       &PrepareItemrecordDisplay
       &GetNoZebraIndexes
+      &BatchModField
     );
 }
 
@@ -3681,6 +3682,106 @@ sub get_biblio_authorised_values {
     return $authorised_values;
 }
 
+=head3 BatchModField
+
+  Mod subfields in field record
+
+  returns 1,$record if succeed
+  returns 0,$record if Action was not processed
+  returns -1 if no record
+  returns -2 if no action done on record
+
+=cut
+
+sub BatchModField {
+    my ( $record, $field, $subfield, $action, $condval, $nocond, $repval ) = @_;
+
+    return -1 unless $record;
+    $condval=NormalizeString($condval);
+    my $condition=qr/$condval/;
+
+    if($action eq "add"){
+        for my $rfield ($record->field($field)){
+            $rfield->add_subfields( $subfield => $repval );
+        }
+        return 1;
+    }elsif($action eq "addfield"){
+        my $new_field = MARC::Field->new($field,'','',
+                                         $subfield => $repval);
+        $record->insert_fields_ordered($new_field);
+        return 1;
+    } else {
+        my $done=0;
+        if ($field eq '000') {
+            my $value=$record->leader();
+            if ($value=~ s/$condition/$repval/){
+                $record->leader($repval);
+                $done=1;
+           }
+           if ( $nocond eq 'true'){
+            $record->leader($repval);
+            $done=1;
+           }
+        }
+        for my $rfield ($record->field($field)) {
+            if ($subfield && $subfield ne "@"){
+                my @subfields = $rfield->subfields();
+                my @subfields_to_add;
+                foreach my $subf (@subfields) {
+                    if ($subf->[0] eq $subfield){
+                        $subf->[1]=NormalizeString($subf->[1]);
+                        if ( $action eq "mod" ) {
+                            if ( $nocond ne "true" && $subf->[1] =~ s/$condition/$repval/) {
+                                $done=1;
+                            }
+                            if ($nocond eq "true"){
+                                $subf->[1] = $repval;
+                                $done=1;
+                            }
+                        } elsif ( $action eq "del" ) {
+                            if ( $subf->[1] =~ m/$condition/ || $nocond eq "true" ) {
+                                $done=1;
+                                next;
+                            }
+                        }
+                    }
+                    push @subfields_to_add,@$subf;
+                }
+                if ($done){
+                    if (@subfields_to_add){
+                        $rfield->replace_with(MARC::Field->new($rfield->tag,$rfield->indicator(1),$rfield->indicator(2),@subfields_to_add));
+                    }
+                    else {
+                        my $count= $record->delete_field($rfield);
+                    }
+                }
+            }
+            else {
+                if ($action eq "del"){
+                    my $count=$record->delete_field($rfield);
+                    $done=1;
+                }
+                else {
+                    if ($field < 10){
+                       my $value=$record->field($field)->data();
+                       if ($value=~ s/$condition/$repval/){
+                            $record->field($field)->update($value);
+                            $done=1;
+
+                       }
+                       if ( $nocond eq 'true'){
+                        $record->field($field)->update($repval);
+                        $done=1;
+                       }
+                    }
+                }
+            }
+        }
+        return ($done,$record);
+    }
+    return -2;
+}
+
 1;
 
 __END__
diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
index bdfc9ac..cf32225 100755
--- a/installer/data/mysql/updatedatabase.pl
+++ b/installer/data/mysql/updatedatabase.pl
@@ -4365,7 +4365,7 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
 
 $DBversion = "3.05.00.004";
 if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
-    $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('ShowReviewerPhoto',1,'If ON, photo of reviewer will be shown beside comments in OPAC',NULL,'YesNo');");
+    $dbh->do("INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('ShowReviewerPhoto',1,'If ON, photo of reviewer will be shown beside comments in OPAC',NULL,'YesNo')");
     print "Upgrade to $DBversion done (Add syspref ShowReviewerPhoto)\n";
     SetVersion($DBversion);    
 }
@@ -4436,6 +4436,12 @@ $DBversion = "3.05.00.010";
 if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
     $dbh->do("CREATE INDEX priorityfoundidx ON reserves (priority,found)");
     print "Create an index on reserves to speed up holds awaiting pickup report bug 5866\n";
+}
+
+$DBversion = "3.05.00.XXX";
+if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+    $dbh->do("INSERT INTO permissions (module_bit, code, description) VALUES ( 13, 'batchedit', 'Batch editing biblios')");
+    print "Upgrade to $DBversion done (batch edit permission)\n";
     SetVersion($DBversion);
 }
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/basket.js b/koha-tmpl/intranet-tmpl/prog/en/js/basket.js
index 9946cf7..03dc306 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/js/basket.js
+++ b/koha-tmpl/intranet-tmpl/prog/en/js/basket.js
@@ -433,4 +433,10 @@ $(document).ready(function(){
 	if(basketcount){ updateBasket(basketcount); }
 });
 
+function batchEdit(){
+    var valCookie = readCookie(nameCookie);
+    var strCookie = nameParam + "=" + valCookie;
 
+    var loc = CGIBIN + "tools/batchedit.pl?" + strCookie;
+    window.opener.location = loc;
+}
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
index 38b25e2..05a8acc 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
@@ -86,6 +86,13 @@ function placeHold () {
 		[% IF ( verbose ) %]<a href="basket.pl" class="brief" onclick="showLess(); return false;">Brief Display</a>[% ELSE %]<a href="basket.pl" class="detail" onclick="showMore(); return false;">More Details</a>[% END %]
 	    </span></span>
 	</li>
+    [% IF ( CAN_user_tools_batchedit ) %]
+    <li>
+        <span id="batchedit" class="yui-button yui-link-button"><span class="first-child">
+        <a class="batchedit" href="basket.pl" onclick="batchEdit(); return false;">Batch Edit</a>
+        </span></span>
+    </li>
+    [% END %]
 	<li>
 	    <span id="receive" class="yui-button yui-link-button"><span class="first-child">
 		<a class="send" href="basket.pl" onclick="sendBasket(); return false;">Send</a>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchedit.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchedit.tt
new file mode 100644
index 0000000..31c84d1
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/batchedit.tt
@@ -0,0 +1,257 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Tools &rsaquo; Batch record of modification</title>
+[% INCLUDE 'doc-head-close.inc' %]
+
+[% UNLESS ( modsuccess ) %]
+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.tablesorter.min.js"></script>
+<script type="text/JavaScript" language="JavaScript">
+//<![CDATA[
+     var CGIBIN = "/cgi-bin/koha/";
+
+     function fieldChanged(){
+        var field = $('#fieldchoice').val();
+        $("#loading").html(" <img src=\"/intranet-tmpl/prog/img/loading-small.gif\" alt=\"\" />");
+        $.ajax({
+		url: CGIBIN + 'tools/batchedit.pl?field=' + field,
+		dataType: 'json',
+            success: function(data){
+            $("#loading").html("");
+		$("#subfieldchoice option").remove();
+
+		    var subfield = $('#subfieldchoice');
+			$("<option>").attr("value", "@")
+                                 .text( _('Whole field'))
+                                 .appendTo('#subfieldchoice');
+                for( var i=0; i < data.length ; i++){
+			$("<option>").attr("value", data[i].subfield)
+                                 .text(data[i].subfield)
+                                 .appendTo('#subfieldchoice');
+                }
+                subfieldChanged();
+            }
+        });
+     }
+
+     function subfieldChanged(){
+        var field    = $('#fieldchoice').val();
+        var subfield = $('#subfieldchoice').val();
+        $.ajax({
+		url: CGIBIN + 'tools/batchedit.pl?field=' + field + '&subfield=' + subfield,
+		dataType: 'json',
+            success: function(data){
+
+		    if( data.length > 0) {
+			$("#condvaltd").html('<select name="condvalchoice" id="condvalchoice" />');
+			$("<option>").attr("value", "")
+                        .text("")
+                        .appendTo('#condvalchoice');
+			$("#repvaltd" ).html('<select name="repvalchoice" id="repvalchoice" />'  );
+                    $("<option>").attr("value", "")
+                        .text("")
+                        .appendTo('#repvalchoice');
+
+                    for( var i=0; i < data.length ; i++){
+			$("<option>").attr("value", data[i].code)
+                            .text(data[i].value)
+                            .appendTo('#repvalchoice');
+			$("<option>").attr("value", data[i].code)
+                            .text(data[i].value)
+                            .appendTo('#condvalchoice');
+                    }
+		    }else{
+                    $("#condvaltd").html('<input type="text" name="condvalchoice" id="condvalchoice" />');
+                    $("#repvaltd").html('<input type="text" name="repvalchoice"  id="repvalchoice" />');
+		    }
+                $('<label> <input type="checkbox" id="nocond" name="nocond" value="nocond" onClick="$(\'#condvalchoice\').attr(\'disabled\', ! $(\'#condvalchoice\').attr(\'disabled\') ) " />  All</label>').appendTo("#condvaltd");
+            }
+        });
+
+     }
+
+     function addRule(){
+        var actionlabel = {
+                mod: _('Modify'),
+                del: _('Delete'),
+                add: _('Create')
+                };
+        var repvallabel  = $('#repvalchoice :selected').text()  || $("#repvalchoice").val();
+
+        var field    = $('#fieldchoice').val();
+        var subfield = $('#subfieldchoice').val();
+        var action   = $('#actionchoice').val();
+        var nocond   = $('#nocond').attr('checked')||(! $('#condvalchoice').val().length);
+
+        if( ! nocond ) {
+            var condval  = $('#condvalchoice').val();
+            var condvallabel = $('#condvalchoice :selected').text() || $("#condvalchoice").val();
+        }else{
+            var condvallabel = _("No condition");
+        }
+        var repval   = $('#repvalchoice').val();
+
+        var tmpl = "<tr>"
+                + '<td><input type="hidden" name="field" value="'    + field + '" />'    + field               + '</td>'
+                + '<td><input type="hidden" name="subfield" value="' + subfield + '" />' + subfield            + '</td>'
+                + '<td><input type="hidden" name="action" value="'   + action + '" />'   + actionlabel[action] + '</td>'
+                + '<td><input type="hidden" name="condval" value="'  + condval + '" />'
+                    + condvallabel
+                    + '<input type="hidden" name="nocondval" value="' + nocond + '" />'
+                + '</td>'
+
+                + '<td><input type="hidden" name="repval" value="'   + repval + '" />'   + repvallabel         + '</td>'
+                + '<td><input type="button" value="Delete" onclick="deleteRule(this)" /></td>'
+            + '</tr>';
+        $('#rulestable').append(tmpl);
+
+     }
+
+     function deleteRule(button){
+        $(button).parent().parent().remove();
+        return false;
+     }
+
+
+//]]>
+</script>
+[% END %]
+</head>
+<body>
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'cat-search.inc' %]
+
+<div id="breadcrumbs">
+  <a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo;
+  <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo;
+  <a href="/cgi-bin/koha/tools/batchedit.pl">Batch record modification</a>
+</div>
+
+<div id="doc3" class="yui-t2">
+    <div id="bd">
+        <div id="yui-main">
+            <div class="yui-b">
+
+<form method="post" action="/cgi-bin/koha/tools/batchedit.pl" enctype="multipart/form-data">
+[% IF ( moddone ) %]
+    <div class="dialog message">All operations processed</div>
+[% END %]
+
+[% UNLESS ( bib_list ) %]
+    <h2>Batch record modification</h2>
+    <div class="yui-g">
+    <div class="yui-u first">
+    <fieldset class="rows">
+	<legend>Use a file of biblionumbers</legend>
+	<ol>
+	    <li><label for="uploadfile">File: </label> <input type="file" id="uploadfile" name="uploadfile" /></li>
+	</ol>
+    </fieldset>
+    </div>
+    <div class="yui-u">
+    <div class="container">
+    <p><b>Reminder</b>: You can also add records to your cart and reach this page from the cart.</p>
+    </div>
+    </div>
+    </div>
+    <fieldset class="rows">
+	<legend>Or enter records one by one</legend>
+	<ol>
+	    <li>
+		<label for="recordslist">One biblionumber per line: </label>
+		<textarea rows="10" cols="30" id="recordslist" name="recordslist"></textarea>
+	    </li>
+	</ol>
+    
+    </fieldset>
+[% ELSE %]
+    <h2>List of records:</h2>
+    <table id="bibliolist">
+        <thead>
+            <tr>
+                <th>Biblionumber</th><th>Title</th><th>Author</th>[% IF ( moddone ) %] <th>Status</th>[% END %]
+            </tr>
+        </thead>
+        [% FOREACH biblioinfo IN biblioinfos %]
+            <tr>
+                <td>[% biblioinfo.biblionumber %]</td>
+                <td>[% biblionumber = biblioinfo.biblionumber %] [% INCLUDE 'biblio-default-view.inc' %][% IF ( biblioinfo.title ) %][% biblioinfo.title |html %][% ELSE %]No title[% END %]</a></td>
+                <td>[% biblioinfo.author %]</td>
+                [% IF ( moddone ) %]
+                    [% IF ( biblioinfo.OK ) %]
+                        <td>
+                    [% ELSE %]
+                        <td class="problem">
+                    [% END %]
+                    [% IF ( biblioinfo.OK ) %]OK[% END %]
+                    [% IF ( biblioinfo.No_Actions ) %]Nothing done[% END %]
+                    [% IF ( biblioinfo.Actions_Failed ) %]
+                        Some actions failed. List follow : <ul>[% FOREACH failed_action IN biblioinfo.failed_actions %]<li>[% failed_action.action %]</li>[% END %]</ul>
+                    [% END %]
+                    </td>
+                [% END %]
+            </tr>
+        [% END %]
+    </table>
+[% END %]
+
+[% UNLESS ( moddone ) %]
+
+    [% IF ( bib_list ) %]
+        <fieldset class="rows">
+        <h2>Modification rules:</h2>
+        <input type="hidden" name="op" value="do" />
+        <input type="hidden" name="bib_list" value="[% bib_list %]" />
+        <table id="rulestable">
+            <thead>
+                <tr>
+                    <th>Field</th><th>Subfield</th><th>Action</th><th>Condition Value</th><th>Value</th><th>&nbsp;</th>
+                </tr>
+            </thead>
+                <tr>
+                    <td>
+                        <select name="fieldchoice" id="fieldchoice" onchange="fieldChanged();">
+                        <option value=""></option>
+                        [% FOREACH marcfield IN marcfields %]
+                            <option value="[% marcfield.tag %]">[% marcfield.tag %]</option>
+                        [% END %]
+                        </select>
+                    </td>
+                    <td>
+                        <select name="subfieldchoice" id="subfieldchoice" onchange="subfieldChanged();">
+                        </select><span id="loading"></span>
+                    </td>
+                    <td>
+                        <select name="actionchoice" id="actionchoice">
+                            <option value="mod">Modify subfield</option>
+                            <option value="add">Create subfield</option>
+                            <option value="addfield">Create field and subfield</option>
+                            <option value="del">Delete subfield</option>
+                        </select>
+                    </td>
+                    <td id="condvaltd">
+                        <input type="text" name="condvalchoice" id="condvalchoice" />
+                        <label> <input type="checkbox" id="nocond" name="nocond" value="nocond" onclick="$('#condvalchoice').attr('disabled', ! $('#condvalchoice').attr('disabled') ) " />  All </label>
+                    </td>
+                    <td id="repvaltd">
+                        <input type="text" name="repvalchoice" id="repvalchoice" />
+                    </td>
+                    <td><input type="button" value="Add" onclick="addRule();" /></td>
+                </tr>
+            </thead>
+
+        </table>
+        <input type="hidden" name="bib_list" value="[% bib_list %]" />
+        <fieldset class="action"><input type="submit" value="Submit" /> (don't forget to click "Add" button on the right of the previous form before submitting)</fieldset>
+        </fieldset>
+        </form>
+    [% ELSE %]
+        <fieldset class="action"><input type="submit" value="Submit" /></fieldset>
+        </form>
+    [% END %]
+[% END %]
+            </div>
+        </div>
+       <div class="yui-b">
+            [% INCLUDE 'tools-menu.inc' %]
+        </div>
+    </div>
+[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
index 10f1d6d..f218202 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt
@@ -103,6 +103,11 @@
     <dd>Modify items in a batch</dd>
     [% END %]
     
+    [% IF ( CAN_user_tools_batchedit ) %]
+    <dt><a href="/cgi-bin/koha/tools/batchedit.pl">Batch biblio modification</a></dt>
+    <dd>Modify biblios in a batch</dd>
+    [% END %]
+    
     [% IF ( CAN_user_tools_export_catalog ) %]
     <dt><a href="/cgi-bin/koha/tools/export.pl">Export bibliographic and holdings</a></dt>
     <dd>Export bibliographic and holdings data</dd>
diff --git a/koha-tmpl/intranet-tmpl/prog/img/loading-small.gif b/koha-tmpl/intranet-tmpl/prog/img/loading-small.gif
new file mode 100644
index 0000000000000000000000000000000000000000..79ea508aa675a47ce0a4a488ed91b7467ab8a4b0
GIT binary patch
literal 1652
zcmZ9MYfMvT9LA3nI&Ot>v4dKm<&@rgETz{YTj+%zTBNdCCMX@3*;+tUgffv4Md?Nj
zAQe#rLB~x%iNF{N8w<F=L}cR<oGj@wh9EfNLJUjz!gkPofW2Se<o!MW=Xw4wqE<<y
zX?Oq+%)$T$gYoqA^!N8Ckw_p2(r7d$lgZ_B`Fy@eB#MlTl*wc&l}e-0Xti3MPM467
zkd%~UFc{L((o7~(W@ct~c6Lrqj>TdrC@3f@Dk?56wpy(=o2{&@%x<?=S6A28);2UW
zG&VN2w6wIhw|91Sc6D|2_V)Jo_YV#Z4i68HjEszpjZI8UOioVD&d$!w%{d&7`T6<9
z#l_|2<<-^IwY9bN_4SR7jm^zXVCSLy<Dre#A5_TVqxldIvkSeYYzE0K8OQU;pJn8k
z$%tA-jysv3VI(8Qw9{k(!~-ZB&Mqzh3~;ud+VTOw-ioR})fOu&jR~4?nz1?$B(tvF
zqfiHaj(SO)D($WHGR9k6Asw6bEIX8S^TivvT`M7Wl+27tyaOasg_H|2QWRXOnx~gD
zsnoCtwS>cFmj#EA`D!tfPG>0ud)53)@)`=QM9Bi#Vmk=c@Fe1hoban9;VD8eoNEK)
z#FcU>odI)b(^OGHSPDA~meAs^%OU1ZO4&}$IKTtdY}nH5VJKA)RjprB^ZLKYG*_AP
z0<2!nsVioY!@cK;ApQJ8{=%aS<^6>A)TSbYh==G;9Xe3KW5&R|aEQfV<j0^=>2!wB
zdQQJThMzBmsPxZKjsGL!0auimutj7Spf2H*GZxxFowEA7Y$fa+mX+v}C3dhe9to+~
z3W)C4sOe5-gyq%;h!Ux(Gjkt<45?HhAp))pCF%r;tbo{TPEm}I!eVo`kuYc;IKcfK
zDgI6<?y^W9hy1a8s_qy3A^D0X$nlsG^hCw0LjJ~oV1$#PZyJa7ggxWkL*?=Pp!U-<
zZFvF%LQ%;%B1A4A1(RtSTZTK<#Y<$i(a*`Zkz7!c2jGR0j8XNkTYQODk)xye2V3gs
z)r#op7CwK$JW8Arv@Jb-)iaiSt8P4Wc(Fn{iCKV&acSRn_jT(d&qny*JPBv%9Mwq#
z=M1VjXrST#0<sfciss1>fYCe(oW`LYq^h@*U4dPwm)<B@KXe7UerctGR-dKZ_ev|$
zWj${m(>{29?Bc$q{ehKJ{k8DrzW6V})6;xH?2oqe`pZ>Lrq-rvvJiB2l>{>Z1{_X@
z)xOR`tz3YyAxuPkY}<%fzzMZ-YsBQJpz-G1a`V88GE0yB@IZ2>xoPZefn#a8om1+i
z^}gH2`xDC0ucrGZUn(^BlQaHWnwMQMg){tw3?Dx!oq*@Kgu)SKUoSWS%QNDu1fDEo
zV1U~2$u=Mca6!|1+sq*!)*be%(_Bg%QW#j?Rbw|65_0a%c33--EPc9_<{owD-Wt2}
za1wGuClofFH}kKJKKu1lDI3GsgNMB7uuv<)2EYLxaELempnEmJE!CfM;KY^P(Mr`e
zB7i#iu9>=_*%jr5m5RqlGTY<>s+i_7!l2RVy=47$V&@4YnyeqM%;=iLsaT5-`G&jk
z?rG^as$UcCib!yXA50_akMP{i2KyEUagQK}Vd@^_WXui>_P<&limI>N?Mt+DB`&Si
zJgktDviypbiSZ7uv8=v_U;8XK@%P&u_6qs(WE8Cq*ZOEAkIPxL!$s*J50Mbwhr@zk
z7FDDY_#dE>4%05Ej={`OxfI^P!k`x7(A17b8Dd)t%T4#H%A2cPl@Hv<RaNzQLT^gW
z_{#Uc?Hzx^{qw`!9$3?+DF7F9H@l*9878^O-Rgv1p&~k4ERJBo5CroBIV`k`MoCBr
z%%Z^@qkt3+v%?BZk`#!UvID&3=2kC1+S>9$oY8e5^9;zz;{+YYy4=(bAdMv#kETy+
zc3l|vIdqHCzOZrL+Msd4fbJQi6sTpT#!3lfh|w*GP8FaFpg{k!c!e-b0JCMlzJCFD
Ci6N~3

literal 0
HcmV?d00001

diff --git a/tools/batchedit.pl b/tools/batchedit.pl
new file mode 100755
index 0000000..73609b9
--- /dev/null
+++ b/tools/batchedit.pl
@@ -0,0 +1,221 @@
+#!/usr/bin/perl
+
+
+# Copyright 2010 SARL BibLibre
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+use CGI;
+use strict;
+use C4::Output;
+use C4::Auth;
+use C4::Branch;
+use C4::Koha;
+use C4::Biblio;
+use C4::Context;
+use C4::Debug;
+use JSON;
+
+my $input = new CGI;
+my $dbh = C4::Context->dbh;
+
+my $filefh = $input->param('uploadfile');
+my $recordslist = $input->param('recordslist');
+my $bib_list = $input->param('bib_list');
+my @biblionumbers;
+
+#retrieve the list of biblionumber, from a file, a list entered manually or the basket
+if ($filefh) {
+    while ( my $biblionumber = <$filefh> ) {
+        $biblionumber =~ s/[\r\n]*$//g;
+        push @biblionumbers, $biblionumber if $biblionumber;
+    }
+} elsif ($recordslist) {
+    push @biblionumbers, split( /\s\n/, $recordslist );
+} elsif ($bib_list) {
+    push @biblionumbers, split('/', $bib_list);
+}
+
+my $op            = $input->param('op');
+my ($template, $loggedinuser, $cookie);
+
+my $frameworkcode="";
+my $tagslib = &GetMarcStructure(1,$frameworkcode);
+my %report_actions;
+
+# if this script is called by ajax, buid an ajax/xml answer
+if($input->param('field') and not defined $op){
+    ($template, $loggedinuser, $cookie)
+        = get_template_and_user({template_name => "acqui/ajax.tmpl",
+                 query => $input,
+                 type => "intranet",
+                 authnotrequired => 0,
+                 flagsrequired => { tools => "batchedit" },
+        });
+
+
+    my $tag      = $input->param('field');
+    my $subfield = $input->param('subfield');
+
+    if($input->param('subfield')){
+        my $branches = GetBranchesLoop();
+
+        my @authorised_values;
+        if ( $tagslib->{$tag}->{$subfield}->{authorised_value} ) {
+             if ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "branches" ) {
+                foreach my $thisbranch (@$branches) {
+                    push @authorised_values, {
+                            code => $thisbranch->{value},
+                            value => $thisbranch->{branchname},
+                        };
+                    # $value = $thisbranch->{value} if $thisbranch->{selected};
+                }
+             }elsif ( $tagslib->{$tag}->{$subfield}->{authorised_value} eq "itemtypes" ) {
+                 my $sth = $dbh->prepare("SELECT itemtype,description FROM itemtypes ORDER BY description");
+                 $sth->execute();
+                 while ( my ( $itemtype, $description ) = $sth->fetchrow_array ) {
+                    push @authorised_values, {
+                        code => $itemtype,
+                        value => $description,
+                    };
+                 }
+
+            }else {
+                  # Getting the fields where the item location is
+                  my ($location_field, $location_subfield) = GetMarcFromKohaField('items.location', $frameworkcode);
+
+                  # Getting the name of the authorised values' category for item location
+                  my $item_location_category = $tagslib->{$location_field}->{$location_subfield}->{'authorised_value'};
+		      # Are we dealing with item location ?
+                  my $item_location = ($tagslib->{$tag}->{$subfield}->{authorised_value} eq $item_location_category) ? 1 : 0;
+
+                  # If so, we sort by authorised_value, else by libelle
+                  my $orderby = $item_location ? 'authorised_value' : 'lib';
+
+                  my $authorised_values_sth = $dbh->prepare("SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY $orderby");
+
+                  $authorised_values_sth->execute( $tagslib->{$tag}->{$subfield}->{authorised_value});
+
+
+                  while ( my ( $value, $lib ) = $authorised_values_sth->fetchrow_array ) {
+                    push @authorised_values, {
+                        code => $value,
+                        value => ($item_location) ? $value . " - " . $lib : $lib,
+                    };
+
+                  }
+            }
+        }
+      $template->param('return' => to_json(\@authorised_values));
+    }else{
+        my @modifiablesubf;
+
+        foreach my $subfield (sort keys %{$tagslib->{$tag}}) {
+            next if subfield_is_koha_internal_p($subfield);
+            next if $subfield eq "@";
+            next if ($tagslib->{$tag}->{$subfield}->{'tab'} eq "10");
+            my %subfield_data;
+            $subfield_data{subfield} = $subfield;
+            push @modifiablesubf, \%subfield_data;
+        }
+        $template->param('return' => to_json(\@modifiablesubf));
+    }
+
+
+    output_html_with_http_headers $input, $cookie, $template->output;
+    exit;
+}else{
+# standard call (via web browser)
+    ($template, $loggedinuser, $cookie)
+            = get_template_and_user({template_name => "tools/batchedit.tmpl",
+                     query => $input,
+                     type => "intranet",
+                     authnotrequired => 0,
+                     flagsrequired => { tools => "batchedit" },
+                     });
+
+    $template->param( bib_list => join('/', @biblionumbers));
+    # if no $op, just display the form
+    if(!defined $op) {
+        my @modifiablefields;
+
+        foreach my $tag (sort keys %{$tagslib}) {
+            my %subfield_data;
+            foreach my $subfield (sort keys %{$tagslib->{$tag}}) {
+                next if $subfield_data{tag};
+                next if subfield_is_koha_internal_p($subfield);
+                next if ($tagslib->{$tag}->{$subfield}->{'tab'} eq "10");
+
+                $subfield_data{tag}      = $tag;
+
+                push @modifiablefields, \%subfield_data;
+            }
+        }
+        $template->param(marcfields  => \@modifiablefields,
+                         );
+
+    }else{
+        my @fields     = $input->param('field');
+        my @subfields  = $input->param('subfield');
+        my @actions    = $input->param('action');
+        my @condvals   = $input->param('condval');
+        my @nocondvals = $input->param('nocondval');
+        my @repvals    = $input->param('repval');
+        foreach my $biblionumber ( @biblionumbers ){
+            my $record = GetMarcBiblio($biblionumber);
+            my ($count, $biblio) = GetBiblio($biblionumber);
+            my @failed_actions;
+            for(my $i = 0 ; $i < scalar(@fields) ; $i++ ){
+                my $field    = $fields[$i];
+                my $subfield = $subfields[$i];
+                my $action   = $actions[$i];
+                my $condval  = $condvals[$i];
+                my $nocond   = $nocondvals[$i];
+                my $repval   = $repvals[$i];
+                my ($result,$record)   = BatchModField($record, $field, $subfield, $action, $condval, $nocond, $repval);
+                push @failed_actions, {action=>"$field $subfield $action ".($nocond eq "true"?"all":$condval)." $repval"} if ($result<=0);
+            }
+            if (@failed_actions == scalar(@fields)){
+                $report_actions{$biblionumber}->{status}="No_Actions";
+            }
+            elsif (@failed_actions>0 and @failed_actions < scalar(@fields)){
+                $report_actions{$biblionumber}->{status}="Actions_Failed";
+                $report_actions{$biblionumber}->{failed_actions}=\@failed_actions;
+            }
+            elsif (@failed_actions == 0){
+                $report_actions{$biblionumber}->{status}="OK";
+            }
+            ModBiblio($record, $biblionumber, $biblio->{frameworkcode});
+        }
+        $template->param('moddone' => 1);
+    }
+
+}
+
+my @biblioinfos;
+
+for my $biblionumber (@biblionumbers){
+    my ($count,$biblio) = GetBiblio($biblionumber);
+    if (defined $op){
+        $biblio->{$report_actions{$biblionumber}->{status}}=1;
+        $biblio->{failed_actions}=$report_actions{$biblionumber}->{failed_actions};
+    }
+    push @biblioinfos, $biblio;
+}
+
+$template->param(biblioinfos => \@biblioinfos);
+output_html_with_http_headers $input, $cookie, $template->output;
+exit;
-- 
1.7.4.1