From 90c243567fcd2fd194ba354c6b93412c2adf4241 Mon Sep 17 00:00:00 2001
From: Jesse Weaver <pianohacker@gmail.com>
Date: Thu, 3 Sep 2015 15:47:35 -0600
Subject: [PATCH] [PASSED QA] Bug 11559: (followup) Prevent saving item tags,
 fix other issues

This fixes the following issues:
  * Spaces are now allowed in indicators
  * Shift-Enter is available to insert a newline if needed
  * Item tags, if present, will prevent saving (as they are not correctly
    processed by the backend)
  * biblionumber tags (999 in MARC21) will be stripped before the record
    is saved to Koha, to prevent their modification

Signed-off-by: Nick Clemens <nick@quecheelibrary.org>

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>
---
 .../lib/koha/cateditor/koha-backend.js             | 28 ++++++++++++++++++++++
 .../lib/koha/cateditor/marc-editor.js              | 13 ++++++++++
 .../lib/koha/cateditor/marc-record.js              | 13 ++++++++++
 .../intranet-tmpl/lib/koha/cateditor/search.js     |  9 ++++++-
 .../intranet-tmpl/lib/koha/cateditor/text-marc.js  |  2 +-
 .../prog/en/includes/cateditor-ui.inc              |  3 +++
 6 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js
index 29287f7..330cfbd 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/koha-backend.js
@@ -21,6 +21,7 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
     var _authorised_values = defaultFramework.authorised_values;
     var _frameworks = {};
     var _framework_mappings = {};
+    var _framework_kohafields = {};
 
     function _fromXMLStruct( data ) {
         result = {};
@@ -48,14 +49,25 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
 
             $.each( taginfo.subfields, function( i, subfield ) {
                 subfields[ subfield[0] ] = subfield[1];
+                if ( frameworkcode == '' && subfield[1].kohafield ) {
+                    _framework_kohafields[ subfield[1].kohafield ] = [ tagnum, subfield[0] ];
+                }
             } );
 
             _framework_mappings[frameworkcode][tagnum] = $.extend( {}, taginfo, { subfields: subfields } );
         } );
+
+        console.dir( _framework_kohafields );
     }
 
     _importFramework( '', defaultFramework.framework );
 
+    function _removeBiblionumberFields( record ) {
+        var bibnumTag = KohaBackend.GetSubfieldForKohaField('biblio.biblionumber')[0];
+
+        while ( record.removeField(bibnumTag) );
+    }
+
     var KohaBackend = {
         NOT_EMPTY: {}, // Sentinel value
 
@@ -72,6 +84,10 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
             return _framework_mappings[frameworkcode][tagnumber];
         },
 
+        GetSubfieldForKohaField: function( kohafield ) {
+            return _framework_kohafields[kohafield];
+        },
+
         GetRecord: function( id, callback ) {
             $.get(
                 '/cgi-bin/koha/svc/bib/' + id
@@ -85,6 +101,9 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
         },
 
         CreateRecord: function( record, callback ) {
+            record = record.clone();
+            _removeBiblionumberFields( record );
+
             $.ajax( {
                 type: 'POST',
                 url: '/cgi-bin/koha/svc/new_bib',
@@ -98,6 +117,9 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
         },
 
         SaveRecord: function( id, record, callback ) {
+            record = record.clone();
+            _removeBiblionumberFields( record );
+
             $.ajax( {
                 type: 'POST',
                 url: '/cgi-bin/koha/svc/bib/' + id,
@@ -186,8 +208,14 @@ define( [ '/cgi-bin/koha/svc/cataloguing/framework?frameworkcode=&callback=defin
             } );
 
             var seenTags = {};
+            var itemTag = KohaBackend.GetSubfieldForKohaField('items.itemnumber')[0];
 
             $.each( record.fields(), function( undef, field ) {
+                if ( field.tagnumber() == itemTag ) {
+                    errors.push( { type: 'itemTagUnsupported', line: field.sourceLine } );
+                    return;
+                }
+
                 if ( seenTags[ field.tagnumber() ] && nonRepeatableTags[ field.tagnumber() ] ) {
                     errors.push( { type: 'unrepeatableTag', line: field.sourceLine, tag: field.tagnumber() } );
                     return;
diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
index 9ee3872..beb7379 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-editor.js
@@ -76,6 +76,12 @@ define( [ 'marc-record', 'koha-backend', 'preferences', 'text-marc', 'widget' ],
         cm.marceditor.startNotify();
     }
 
+    function editorSetOverwriteMode( cm, newState ) {
+        var editor = cm.marceditor;
+
+        editor.overwriteMode = newState;
+    }
+
     // Editor helper functions
     function activateTabPosition( cm, pos, idx ) {
         // Allow tabbing to as-yet-nonexistent positions
@@ -133,6 +139,12 @@ define( [ 'marc-record', 'koha-backend', 'preferences', 'text-marc', 'widget' ],
             cm.setCursor( { line: cursor.line + 1, ch: 0 } );
         },
 
+        'Shift-Enter': function( cm ) {
+            var cur = cm.getCursor();
+
+            cm.replaceRange( "\n", cur, null );
+        },
+
         'Ctrl-X': function( cm ) {
             // Delete line (or cut)
             if ( cm.somethingSelected() ) return true;
@@ -450,6 +462,7 @@ define( [ 'marc-record', 'koha-backend', 'preferences', 'text-marc', 'widget' ],
         this.cm.on( 'beforeChange', editorBeforeChange );
         this.cm.on( 'changes', editorChanges );
         this.cm.on( 'cursorActivity', editorCursorActivity );
+        this.cm.on( 'overwriteToggle', editorSetOverwriteMode );
 
         this.onCursorActivity = options.onCursorActivity;
 
diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-record.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-record.js
index 1e57904..d09f894 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-record.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/marc-record.js
@@ -61,6 +61,10 @@ define( function() {
     }
 
     $.extend( MARC.Record.prototype, {
+        clone: function() {
+            return new MARC.Record( $.map( this.fields(), function( field ) { return field.clone() } ) );
+        },
+
         leader: function(val) {
             var field = this.field('000');
 
@@ -271,6 +275,15 @@ define( function() {
     };
 
     $.extend( MARC.Field.prototype, {
+        clone: function() {
+            return new MARC.Field(
+                this._tagnumber,
+                this._indicators[0],
+                this._indicators[1],
+                $.extend( true, [], this._subfields ) // Deep copy
+            );
+        },
+
         tagnumber: function() {
             return this._tagnumber;
         },
diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js
index bbddc23..0ace7ad 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/search.js
@@ -17,7 +17,7 @@
  * along with Koha; if not, see <http://www.gnu.org/licenses>.
  */
 
-define( [ 'marc-record' ], function( MARC ) {
+define( [ 'koha-backend', 'marc-record' ], function( KohaBackend, MARC ) {
     var _options;
     var _records = {};
     var _last;
@@ -71,6 +71,8 @@ define( [ 'marc-record' ], function( MARC ) {
                 options: options,
             };
 
+            var itemTag = KohaBackend.GetSubfieldForKohaField('items.itemnumber')[0];
+
             $.each( servers, function ( id, info ) {
                 if ( info.checked ) Search.includedServers.push( id );
             } );
@@ -95,6 +97,11 @@ define( [ 'marc-record' ], function( MARC ) {
                         var record = new MARC.Record();
                         record.loadMARCXML( hit.record );
                         hit.record = record;
+
+                        if ( hit.server == 'koha:biblioserver' ) {
+                            // Remove item tags
+                            while ( record.removeField(itemTag) );
+                        }
                     } );
 
                     _options.onresults( data );
diff --git a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/text-marc.js b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/text-marc.js
index 778b4cc..2110652 100644
--- a/koha-tmpl/intranet-tmpl/lib/koha/cateditor/text-marc.js
+++ b/koha-tmpl/intranet-tmpl/lib/koha/cateditor/text-marc.js
@@ -72,7 +72,7 @@ define( [ 'marc-record' ], function( MARC ) {
                     field.sourceLine = i;
                     record.addField( field );
                 } else {
-                    var indicators = line.match( /^... ([0-9A-Za-z_]) ([0-9A-Za-z_])/ );
+                    var indicators = line.match( /^... ([0-9A-Za-z_ ]) ([0-9A-Za-z_ ])/ );
                     if ( !indicators ) {
                         errors.push( { type: 'noIndicators', line: i } );
                         return;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc
index 0616536..0bfeb0a 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cateditor-ui.inc
@@ -842,6 +842,9 @@ require( [ 'koha-backend', 'search', 'macros', 'marc-editor', 'marc-record', 'pr
                         case 'unrepeatableSubfield':
                             editor.addError( error.line, _("Subfield $") + error.subfield + _(" cannot be repeated") );
                             break;
+                        case 'itemTagUnsupported':
+                            editor.addError( error.line, _("Item tags cannot currently be saved") );
+                            break;
                     }
                 } );
 
-- 
1.9.1