View | Details | Raw Unified | Return to bug 5478
Collapse All | Expand All

(-)a/C4/ImportExportFramework.pm (+986 lines)
Line 0 Link Here
1
package C4::ImportExportFramework;
2
3
# Copyright 2010-2011 MASmedios.com y Ministerio de Cultura
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
use XML::LibXML;
23
use XML::LibXML::XPathContext;
24
use Digest::MD5 qw(md5_base64);
25
use POSIX qw(strftime);
26
27
use C4::Context;
28
use C4::Debug;
29
30
31
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
32
33
BEGIN {
34
    $VERSION = 3.03;    # set version for version checking
35
    require Exporter;
36
    @ISA    = qw(Exporter);
37
    @EXPORT = qw(
38
        &ExportFramework
39
        &ImportFramework
40
        &createODS
41
    );
42
}
43
44
45
use constant XMLSTR => '<?xml version="1.0" encoding="UTF-8"?>
46
<?mso-application progid="Excel.Sheet"?>
47
<Workbook
48
  xmlns:x="urn:schemas-microsoft-com:office:excel"
49
  xmlns="urn:schemas-microsoft-com:office:spreadsheet"
50
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
51
52
<Styles>
53
 <Style ss:ID="Default" ss:Name="Normal">
54
  <Alignment ss:Vertical="Bottom"/>
55
  <Borders/>
56
  <Font/>
57
  <Interior/>
58
  <NumberFormat/>
59
  <Protection/>
60
 </Style>
61
 <Style ss:ID="s27">
62
  <Font x:Family="Swiss" ss:Color="#0000FF" ss:Bold="1"/>
63
 </Style>
64
 <Style ss:ID="s21">
65
  <NumberFormat ss:Format="yyyy\-mm\-dd"/>
66
 </Style>
67
 <Style ss:ID="s22">
68
  <NumberFormat ss:Format="yyyy\-mm\-dd\ hh:mm:ss"/>
69
 </Style>
70
 <Style ss:ID="s23">
71
  <NumberFormat ss:Format="hh:mm:ss"/>
72
 </Style>
73
</Styles>
74
75
</Workbook>
76
';
77
78
79
use constant ODSSTR => '<?xml version="1.0" encoding="UTF-8"?>
80
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0">
81
<office:scripts/>
82
<office:font-face-decls/>
83
<office:automatic-styles/>
84
</office:document-content>';
85
86
87
use constant ODS_STYLES_STR => '<?xml version="1.0" encoding="UTF-8"?>
88
<office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" office:version="1.0">
89
<office:font-face-decls></office:font-face-decls>
90
<office:styles></office:styles>
91
<office:automatic-styles></office:automatic-styles>
92
<office:master-styles></office:master-styles>
93
</office:document-styles>';
94
95
96
use constant ODS_SETTINGS_STR => '<?xml version="1.0" encoding="UTF-8"?>
97
<office:document-settings xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.0"><office:settings>
98
<config:config-item-set config:name="ooo:view-settings">
99
<config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item>
100
<config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item>
101
<config:config-item config:name="VisibleAreaWidth" config:type="int">2000</config:config-item>
102
<config:config-item config:name="VisibleAreaHeight" config:type="int">900</config:config-item>
103
<config:config-item-map-indexed config:name="Views"><config:config-item-map-entry>
104
<config:config-item config:name="ViewId" config:type="string">View1</config:config-item>
105
<config:config-item-map-named config:name="Tables">
106
<config:config-item-map-entry config:name="Sheet1"><config:config-item config:name="CursorPositionX" config:type="int">0</config:config-item><config:config-item config:name="CursorPositionY" config:type="int">1</config:config-item><config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item><config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item><config:config-item config:name="HorizontalSplitPosition" config:type="int">0</config:config-item><config:config-item config:name="VerticalSplitPosition" config:type="int">0</config:config-item><config:config-item config:name="ActiveSplitRange" config:type="short">2</config:config-item><config:config-item config:name="PositionLeft" config:type="int">0</config:config-item><config:config-item config:name="PositionRight" config:type="int">0</config:config-item><config:config-item config:name="PositionTop" config:type="int">0</config:config-item><config:config-item config:name="PositionBottom" config:type="int">0</config:config-item>
107
</config:config-item-map-entry>
108
</config:config-item-map-named>
109
<config:config-item config:name="ActiveTable" config:type="string">Sheet1</config:config-item>
110
<config:config-item config:name="HorizontalScrollbarWidth" config:type="int">270</config:config-item>
111
<config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
112
<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item>
113
<config:config-item config:name="PageViewZoomValue" config:type="int">50</config:config-item>
114
<config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>
115
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item>
116
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item>
117
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
118
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item>
119
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item>
120
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>
121
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item>
122
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item>
123
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item>
124
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item>
125
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item></config:config-item-map-entry></config:config-item-map-indexed>
126
</config:config-item-set>
127
<config:config-item-set config:name="ooo:configuration-settings">
128
<config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item>
129
<config:config-item config:name="ShowNotes" config:type="boolean">true</config:config-item>
130
<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
131
<config:config-item config:name="GridColor" config:type="long">12632256</config:config-item>
132
<config:config-item config:name="ShowPageBreaks" config:type="boolean">true</config:config-item>
133
<config:config-item config:name="LinkUpdateMode" config:type="short">3</config:config-item>
134
<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>
135
<config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item>
136
<config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item>
137
<config:config-item config:name="IsSnapToRaster" config:type="boolean">false</config:config-item>
138
<config:config-item config:name="RasterIsVisible" config:type="boolean">false</config:config-item>
139
<config:config-item config:name="IsRasterAxisSynchronized" config:type="boolean">true</config:config-item>
140
<config:config-item config:name="AutoCalculate" config:type="boolean">true</config:config-item>
141
<config:config-item config:name="PrinterName" config:type="string">Generic Printer</config:config-item>
142
<config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
143
<config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
144
<config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
145
<config:config-item config:name="UpdateFromTemplate" config:type="boolean">false</config:config-item>
146
<config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item>
147
<config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
148
</config:config-item-set>
149
</office:settings></office:document-settings>';
150
151
152
use constant ODS_MANIFEST_STR => '<?xml version="1.0" encoding="UTF-8"?>
153
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
154
 <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
155
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/statusbar/"/>
156
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/"/>
157
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/floater/"/>
158
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/popupmenu/"/>
159
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/progressbar/"/>
160
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/menubar/"/>
161
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/toolbar/"/>
162
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/Bitmaps/"/>
163
 <manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/"/>
164
 <manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
165
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
166
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
167
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
168
 <manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/>
169
 <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
170
</manifest:manifest>';
171
172
173
=head1 NAME
174
175
C4::ImportExportFramework - Import/Export Framework to Excel-xml/ODS Module Functions
176
177
=head1 SYNOPSIS
178
179
  use C4::ImportExportFramework;
180
181
=head1 DESCRIPTION
182
183
Module to Import/Export Framework to Excel-xml/ODS on intranet administration - MARC Frameworks section
184
185
Module to Import/Export Framework to Excel-xml/ODS on intranet administration - MARC Frameworks section
186
exporting the tables marc_tag_structure, marc_subfield_structure to excel-xml/ods or viceversa
187
188
Functions for handling import/export.
189
190
191
=head1 SUBROUTINES
192
193
194
195
=head2 ExportFramework
196
197
Export all the information of a Framework to an excel "xml" file or OpenDocument SpreadSheet "ods" file.
198
199
return :
200
succes
201
202
=cut
203
204
sub ExportFramework
205
{
206
    my ($frameworkcode, $xmlStrRef, $mode) = @_;
207
208
    my $dbh = C4::Context->dbh;
209
    if ($dbh) {
210
        my $dom;
211
        my $root;
212
        my $elementSS;
213
        eval {
214
            my $parser = XML::LibXML->new();
215
            $dom = $parser->parse_string(($mode && $mode eq 'ods')?ODSSTR:XMLSTR);
216
            if ($dom) {
217
                $root = $dom->documentElement();
218
                if ($mode && $mode eq 'ods') {
219
                    my $elementBody = $dom->createElement('office:body');
220
                    $root->appendChild($elementBody);
221
                    $elementSS = $dom->createElement('office:spreadsheet');
222
                    $elementBody->appendChild($elementSS);
223
                }
224
            }
225
        };
226
        if ($@) {
227
            $debug and warn "Error ExportFramework $@\n";
228
            return 0;
229
        }
230
        if (_export_table('marc_tag_structure', $dbh, $dom, ($mode && $mode eq 'ods')?$elementSS:$root, $frameworkcode, $mode)) {
231
            if (_export_table('marc_subfield_structure', $dbh, $dom, ($mode && $mode eq 'ods')?$elementSS:$root, $frameworkcode, $mode)) {
232
                $$xmlStrRef = $dom->toString(1);
233
                return 1;
234
            }
235
        }
236
    }
237
    return 0;
238
}#ExportFramework
239
240
241
242
243
# Export all the data from a mysql table to an spreadsheet.
244
sub _export_table
245
{
246
    my ($table, $dbh, $dom, $root, $frameworkcode, $mode) = @_;
247
    
248
    if ($mode && $mode eq 'ods') {
249
        _export_table_ods($table, $dbh, $dom, $root, $frameworkcode);
250
    } else {
251
        _export_table_excel($table, $dbh, $dom, $root, $frameworkcode);
252
    }
253
}
254
255
256
# Export the mysql table to an ods file
257
sub _export_table_ods
258
{
259
    my ($table, $dbh, $dom, $root, $frameworkcode) = @_;
260
    
261
    eval {
262
        my $elementTable = $dom->createElement('table:table');
263
        $elementTable->setAttribute('table:name', $table);
264
        $elementTable->setAttribute('table:print', 'false');
265
        $root->appendChild($elementTable);
266
        my $elementRow = $dom->createElement('table:table-row');
267
        $elementTable->appendChild($elementRow);
268
269
        my $elementCell;
270
        my $elementData;
271
        # First row with the name of the columns
272
        my $query = 'SHOW COLUMNS FROM ' . $table;
273
        my $sth = $dbh->prepare($query);
274
        $sth->execute();
275
        my @fields = ();
276
        while (my $hashRef = $sth->fetchrow_hashref) {
277
            $elementCell = $dom->createElement('table:table-cell');
278
            $elementCell->setAttribute('office:value-type', 'string');
279
            $elementCell->setAttribute('office:value', $hashRef->{Field});
280
            $elementRow->appendChild($elementCell);
281
            $elementData = $dom->createElement('text:p');
282
            $elementCell->appendChild($elementData);
283
            $elementData->appendTextNode($hashRef->{Field});
284
            push @fields, {name => $hashRef->{Field}, type => ($hashRef->{Type} =~ /int/i)?'float':'string'};
285
        }
286
        # Populate rows with the data from mysql
287
        $query = 'SELECT * FROM ' . $table . ' WHERE frameworkcode=?';
288
        $sth = $dbh->prepare($query);
289
        $sth->execute($frameworkcode);
290
        my $data;
291
        while (my $hashRef = $sth->fetchrow_hashref) {
292
            $elementRow = $dom->createElement('table:table-row');
293
            $elementTable->appendChild($elementRow);
294
            for (@fields) {
295
                $data = $hashRef->{$_->{name}};
296
                if ($_->{type} eq 'float' && !defined($data)) {
297
                    $data = '0';
298
                } elsif ($_->{type} eq 'string' && (!$data && $data ne '0')) {
299
                    $data = '#';
300
                }
301
                $data = _parseContent2Xml($data) if ($_->{type} eq 'string');
302
                $elementCell = $dom->createElement('table:table-cell');
303
                $elementCell->setAttribute('office:value-type', $_->{type});
304
                $elementCell->setAttribute('office:value', $data);
305
                $elementRow->appendChild($elementCell);
306
                $elementData = $dom->createElement('text:p');
307
                $elementCell->appendChild($elementData);
308
                $elementData->appendTextNode($data);
309
            }
310
        }
311
    };
312
    if ($@) {
313
        $debug and warn "Error _export_table_ods $@\n";
314
        return 0;
315
    }
316
    return 1;
317
}#_export_table_ods
318
319
320
# Export the mysql table to an excel-xml (openoffice/libreoffice compatible) file
321
sub _export_table_excel
322
{
323
    my ($table, $dbh, $dom, $root, $frameworkcode) = @_;
324
    
325
    eval {
326
        my $elementWS = $dom->createElement('Worksheet');
327
        $elementWS->setAttribute('ss:Name', $table);
328
        $root->appendChild($elementWS);
329
        my $elementTable = $dom->createElement('ss:Table');
330
        $elementWS->appendChild($elementTable);
331
        my $elementRow = $dom->createElement('ss:Row');
332
        $elementTable->appendChild($elementRow);
333
334
        # First row with the name of the columns
335
        my $elementCell;
336
        my $elementData;
337
        my $query = 'SHOW COLUMNS FROM ' . $table;
338
        my $sth = $dbh->prepare($query);
339
        $sth->execute();
340
        my @fields = ();
341
        while (my $hashRef = $sth->fetchrow_hashref) {
342
            $elementCell = $dom->createElement('ss:Cell');
343
            $elementCell->setAttribute('ss:StyleID', 's27');
344
            $elementRow->appendChild($elementCell);
345
            $elementData = $dom->createElement('ss:Data');
346
            $elementData->setAttribute('ss:Type', 'String');
347
            $elementCell->appendChild($elementData);
348
            $elementData->appendTextNode($hashRef->{Field});
349
            push @fields, {name => $hashRef->{Field}, type => ($hashRef->{Type} =~ /int/i)?'Number':'String'};
350
        }
351
        # Populate rows with the data from mysql
352
        $query = 'SELECT * FROM ' . $table . ' WHERE frameworkcode=?';
353
        $sth = $dbh->prepare($query);
354
        $sth->execute($frameworkcode);
355
        my $data;
356
        while (my $hashRef = $sth->fetchrow_hashref) {
357
            $elementRow = $dom->createElement('ss:Row');
358
            $elementTable->appendChild($elementRow);
359
            for (@fields) {
360
                $elementCell = $dom->createElement('ss:Cell');
361
                $elementRow->appendChild($elementCell);
362
                $elementData = $dom->createElement('ss:Data');
363
                $elementData->setAttribute('ss:Type', $_->{type});
364
                $elementCell->appendChild($elementData);
365
                $data = $hashRef->{$_->{name}};
366
                if ($_->{type} eq 'Number' && !defined($data)) {
367
                    $data = '0';
368
                } elsif ($_->{type} eq 'String' && (!$data && $data ne '0')) {
369
                    $data = '#';
370
                }
371
                $elementData->appendTextNode(($_->{type} eq 'String')?_parseContent2Xml($data):$data);
372
            }
373
        }
374
    };
375
    if ($@) {
376
        $debug and warn "Error _export_table_excel $@\n";
377
        return 0;
378
    }
379
    return 1;
380
}#_export_table_excel
381
382
383
384
385
386
387
388
# Format chars problematics to a correct format for xml.
389
sub _parseContent2Xml
390
{
391
    my $content = shift;
392
    
393
    $content =~ s/\&(?![a-zA-Z#0-9]{1,4};)/&amp;/g;
394
    $content =~ s/</&lt;/g;
395
    $content =~ s/>/&gt;/g;
396
    return $content;
397
}#_parseContent2Xml
398
399
400
# Get the tmp directory on the system
401
sub _getTmp
402
{
403
    my $tmp = '/tmp';
404
    if ($ENV{'TMP'} && -d $ENV{'TMP'}) {
405
        $tmp = $ENV{'TMP'};
406
    } elsif ($ENV{'TMPDIR'} && -d $ENV{'TMPDIR'}) {
407
        $tmp = $ENV{'TMPDIR'};
408
    } elsif ($ENV{'TEMP'} && -d $ENV{'TEMP'}) {
409
        $tmp = $ENV{'TEMP'};
410
    }
411
    return $tmp;
412
}#_getTmp
413
414
415
# Create our tempdir directory for the ods process
416
sub _createTmpDir
417
{
418
    my $tmp = shift;
419
420
    my $tempdir = (-d $tmp)?$tmp . '/':'./';
421
    $tempdir .= 'tmp_ods_' . Digest::MD5::md5_hex(Digest::MD5::md5_hex(time().{}.rand().{}.$$));
422
    eval {
423
        mkdir $tempdir;
424
    };
425
    if ($@) {
426
        return undef;
427
    } else {
428
        return $tempdir;
429
    }
430
}#_createTmpDir
431
432
=head2 createODS
433
434
Creates a temporary directory to create the ods file and read it to store its content in a string.
435
436
return :
437
success
438
439
=cut
440
441
sub createODS
442
{
443
    my ($strContent, $lang, $strODSRef) = @_;
444
445
    my $tmp = _getTmp();
446
    my $tempModule = 1;
447
    my $tempdir;
448
    eval {
449
        require File::Temp;
450
        import File::Temp qw/ tempfile tempdir /;
451
        $tempdir = tempdir ( 'tmp_ods_' . $$ . '_XXXXXXXX', DIR => (-d $tmp)?$tmp:'.', CLEANUP => 1);
452
    };
453
    if ($@) {
454
        $tempModule = 0;
455
        $tempdir = _createTmpDir($tmp);
456
    }
457
    if ($tempdir) {
458
        # populate tempdir directory with the ods elements
459
        eval {
460
            if (open(OUT, "> $tempdir/content.xml")) {
461
                print OUT $strContent;
462
                close(OUT);
463
            }
464
            if (open(OUT, "> $tempdir/mimetype")) {
465
                print OUT 'application/vnd.oasis.opendocument.spreadsheet';
466
                close(OUT);
467
            }
468
            if (open(OUT, "> $tempdir/meta.xml")) {
469
                print OUT _getMeta($lang);
470
                close(OUT);
471
            }
472
            if (open(OUT, "> $tempdir/styles.xml")) {
473
                print OUT ODS_STYLES_STR;
474
                close(OUT);
475
            }
476
            if (open(OUT, "> $tempdir/settings.xml")) {
477
                print OUT ODS_SETTINGS_STR;
478
                close(OUT);
479
            }
480
            mkdir($tempdir.'/META-INF/');
481
            mkdir($tempdir.'/Configurations2/');
482
            mkdir($tempdir.'/Configurations2/acceleator/');
483
            mkdir($tempdir.'/Configurations2/images/');
484
            mkdir($tempdir.'/Configurations2/popupmenu/');
485
            mkdir($tempdir.'/Configurations2/statusbar/');
486
            mkdir($tempdir.'/Configurations2/floater/');
487
            mkdir($tempdir.'/Configurations2/menubar/');
488
            mkdir($tempdir.'/Configurations2/progressbar/');
489
            mkdir($tempdir.'/Configurations2/toolbar/');
490
            if (open(OUT, "> $tempdir/META-INF/manifest.xml")) {
491
                print OUT ODS_MANIFEST_STR;
492
                close(OUT);
493
            }
494
        };
495
        if ($@) {
496
            $debug and warn "Error createODS $@\n";
497
        } else {
498
            # create ods file from tempdir directory
499
            eval {
500
                require Archive::Zip;
501
                import Archive::Zip qw( :ERROR_CODES :CONSTANTS );
502
                my $zip = Archive::Zip->new();
503
                $zip->addTree( $tempdir, '' );
504
                $zip->writeToFileNamed('new.ods');
505
            };
506
            if ($@) {
507
                system("cd $tempdir && zip -r new.ods ./");
508
            }
509
            my $ok = 0;
510
            # read ods file and return as a string
511
            if (-f "$tempdir/new.ods") {
512
                if (open (MYFILE, "$tempdir/new.ods")) {
513
                    binmode MYFILE;
514
                    my $buffer;
515
                    while (read (MYFILE, $buffer, 65536)) {
516
                        $$strODSRef .= $buffer;
517
                    }
518
                    close(MYFILE);
519
                    $ok = 1;
520
                }
521
            }
522
            # delete tempdir directory
523
            if (!$tempModule && $tempdir) {
524
                eval {
525
                    require File::Path;
526
                    import File::Temp qw/ rmtree /;
527
                    rmtree($tempdir);
528
                };
529
                if ($@) {
530
                    system("rm -rf $tempdir");
531
                }
532
            }
533
            return 1 if ($ok);
534
        }
535
    }
536
    return 0;
537
}#createODS
538
539
540
# return Meta content for ods file
541
sub _getMeta
542
{
543
    my $lang = shift;
544
545
    my $myDate = strftime ("%Y-%m-%dT%H:%M:%S", localtime(time()));
546
    my $meta = '<?xml version="1.0" encoding="UTF-8"?>
547
    <office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.0">
548
        <office:meta>
549
            <meta:generator>ods-php</meta:generator>
550
            <meta:creation-date>' . $myDate . '</meta:creation-date>
551
            <dc:date>' . $myDate . '</dc:date>
552
            <dc:language>' . $lang . '</dc:language>
553
            <meta:editing-cycles>2</meta:editing-cycles>
554
            <meta:editing-duration>PT15S</meta:editing-duration>
555
            <meta:user-defined meta:name="Info 1"/>
556
            <meta:user-defined meta:name="Info 2"/>
557
            <meta:user-defined meta:name="Info 3"/>
558
            <meta:user-defined meta:name="Info 4"/>
559
        </office:meta>
560
    </office:document-meta>';
561
    return $meta;
562
}#_getMeta
563
564
565
=head2 ImportFramework
566
567
Import all the information of a Framework from a excel-xml/ods file.
568
569
return :
570
success
571
572
=cut
573
574
sub ImportFramework
575
{
576
    my ($filename, $frameworkcode, $deleteFilename) = @_;
577
578
    my $tempdir;
579
    my $ok = -1;
580
    my $dbh = C4::Context->dbh;
581
    if (-r $filename && $dbh) {
582
        my $extension = '';
583
        if ($filename =~ /\.(ods|xml)$/i) {
584
            $extension = lc($1);
585
        } else {
586
            unlink ($filename) if ($deleteFilename);
587
            return -1;
588
        }
589
        if ($extension eq 'ods') {
590
            ($tempdir, $filename) = _openODS($filename, $deleteFilename);
591
        }
592
        if ($filename) {
593
            eval {
594
                my $parser = XML::LibXML->new();
595
                my $dom = $parser->parse_file($filename);
596
                if ($dom) {
597
                    my $element;
598
                    my $root = $dom->documentElement();
599
                    my $numDeleted = 0;
600
                    my $numDeletedAux = 0;
601
                    if (($numDeletedAux = _import_table($dbh, 'marc_tag_structure', $frameworkcode, $dom, ['frameworkcode', 'tagfield'], $extension)) >= 0) {
602
                        $numDeleted += $numDeletedAux if ($numDeletedAux > 0);
603
                        if (($numDeletedAux = _import_table($dbh, 'marc_subfield_structure', $frameworkcode, $dom, ['frameworkcode', 'tagfield', 'tagsubfield'], $extension)) >= 0) {
604
                            $numDeleted += $numDeletedAux if ($numDeletedAux > 0);
605
                            $ok = ($numDeleted > 0)?$numDeleted:0;
606
                        }
607
                    }
608
                } else {
609
                    $debug and warn "Error ImportFramework couldn't create dom\n";
610
                }
611
            };
612
            if ($@) {
613
                $debug and warn "Error ImportFramework $@\n";
614
            }
615
        }
616
        unlink ($filename) if ($deleteFilename);
617
    } else {
618
        $debug and warn "Error ImportFramework no conex to database or not readeable $filename\n";
619
    }
620
    if ($deleteFilename && $tempdir && -d $tempdir && -w $tempdir) {
621
        eval {
622
            require File::Path;
623
            import File::Temp qw/ rmtree /;
624
            rmtree($tempdir);
625
        };
626
        if ($@) {
627
            system("rm -rf $tempdir");
628
        }
629
    }
630
    return $ok;
631
}#ImportFramework
632
633
634
# Open (uncompress) ods file and return the content.xml file
635
sub _openODS
636
{
637
    my ($filename, $deleteFilename) = @_;
638
    
639
    my $tmp = _getTmp();
640
    my $tempModule = 1;
641
    my $tempdir;
642
    eval {
643
        require File::Temp;
644
        import File::Temp qw/ tempfile tempdir /;
645
        $tempdir = tempdir ( 'tmp_ods_' . $$ . '_XXXXXXXX', DIR => (-d $tmp)?$tmp:'.', CLEANUP => 0);
646
    };
647
    if ($@) {
648
        $tempModule = 0;
649
        $tempdir = _createTmpDir($tmp);
650
    }
651
    if ($tempdir) {
652
        eval {
653
            require Archive::Zip;
654
            import Archive::Zip qw( :ERROR_CODES :CONSTANTS );
655
            my $zip = Archive::Zip->new();
656
            $zip->extractTree( $filename, $tempdir );
657
        };
658
        if ($@) {
659
            system("unzip $filename -d $tempdir");
660
        }
661
        if (-f "$tempdir/content.xml") {
662
            unlink ($filename) if ($deleteFilename);
663
            return ($tempdir, "$tempdir/content.xml");
664
        }
665
    }
666
    unlink ($filename) if ($deleteFilename);
667
    return ($tempdir, undef);
668
}#_openODS
669
670
671
672
# Check the table and columns corresponds with worksheet
673
sub _check_validity_worksheet
674
{
675
    my ($dbh, $table, $nodeFields, $fieldsA, $format) = @_;
676
677
    my $ret = 0;
678
    eval {
679
        my $query = 'DESCRIBE ' . $table;
680
        my $sth = $dbh->prepare($query);
681
        $sth->execute();
682
        $sth->finish;
683
        $query = 'SHOW COLUMNS FROM ' . $table;
684
        $sth = $dbh->prepare($query);
685
        $sth->execute();
686
        my $fields = {};
687
        while (my $hashRef = $sth->fetchrow_hashref) {
688
            $fields->{$hashRef->{Field}} = $hashRef->{Field};
689
        }
690
        my @fields;
691
        my $fieldsR;
692
        if ($fieldsA) {
693
            $fieldsR = $fieldsA;
694
        } else {
695
            $fieldsR = \@fields;
696
            _getFields($nodeFields, $fieldsR, $format);
697
        }
698
        $ret = 1;
699
        for (@$fieldsR) {
700
            unless (exists($fields->{$_})) {
701
                $ret = 0;
702
                last;
703
            }
704
        }
705
    };
706
    return $ret;
707
}#_check_validity_worksheet
708
709
710
# Import the data from an excel-xml/ods to mysql tables.
711
sub _import_table
712
{
713
    my ($dbh, $table, $frameworkcode, $dom, $PKArray, $format) = @_;
714
    my %fields2Delete;
715
    my $query;
716
    eval {
717
        my @fields = @$PKArray;
718
        shift @fields;
719
        $query = 'SELECT ' . join(',', @fields) . ' FROM ' . $table . ' WHERE frameworkcode=?';
720
        my $sth = $dbh->prepare($query);
721
        $sth->execute($frameworkcode);
722
        my $field;
723
        while (my $hashRef = $sth->fetchrow_hashref) {
724
            $field = '';
725
            map { $field .= $hashRef->{$_} . '_'; } @fields;
726
            chop $field;
727
            $fields2Delete{$field} = 1;
728
        }
729
        $sth->finish;
730
    };
731
    my $ok = 0;
732
    if ($format && $format eq 'ods') {
733
        $ok = _import_table_ods($dbh, $table, $frameworkcode, $dom, $PKArray, \%fields2Delete);
734
    } else {
735
        $ok = _import_table_excel($dbh, $table, $frameworkcode, $dom, $PKArray, \%fields2Delete);
736
    }
737
    if ($ok) {
738
        if (($ok = scalar(keys %fields2Delete)) > 0) {
739
            $query = 'DELETE FROM ' . $table . ' WHERE ';
740
            map {$query .= $_ . '=? AND ';} @$PKArray;
741
            $query = substr($query, 0, -4);
742
            my $sth = $dbh->prepare($query);
743
            for (keys %fields2Delete) {
744
                eval {
745
                    $sth->execute(($frameworkcode, split('_', $_)));
746
                };
747
            }
748
        }
749
    } else {
750
        $ok = -1;
751
    }
752
    return $ok;
753
}#_import_table
754
755
756
# Process the rows of a worksheet and insert/update them in a mysql table.
757
sub _processRows_Table
758
{
759
    my ($dbh, $frameworkcode, $nodeR, $table, $PKArray, $format, $fields2Delete) = @_;
760
    
761
    my $query;
762
    my @fields = ();
763
    my $fields = '';
764
    my $dataStr = '';
765
    my $updateStr = '';
766
    my $j = 0;
767
    my $db_scheme = C4::Context->config("db_scheme");
768
    my $ok = 0;
769
    my @fieldsPK = @$PKArray;
770
    shift @fieldsPK;
771
    while ($nodeR) {
772
        if ($nodeR->nodeType == 1 && (($format && $format eq 'ods' && $nodeR->nodeName =~ /(?:table:)?table-row/) || ($nodeR->nodeName =~ /(?:ss:)?Row/)) && $nodeR->hasChildNodes()) {
773
            if ($j == 0) {
774
                # Get name columns
775
                _getFields($nodeR, \@fields, $format);
776
                return 0 unless _check_validity_worksheet($dbh, $table, $nodeR, \@fields, $format);
777
                $fields = join(',', @fields);
778
                $dataStr = '';
779
                map { $dataStr .= '?,';} @fields;
780
                chop($dataStr) if ($dataStr);
781
                $updateStr = '';
782
                map { $updateStr .= $_ . '=?,';} @fields;
783
                chop($updateStr) if ($updateStr);
784
            } else {
785
                # Get data from row
786
                my ($dataFields, $dataFieldsR) = _getDataFields($frameworkcode, $nodeR, \@fields, $format);
787
                if (scalar(@fields) == scalar(@$dataFieldsR)) {
788
                    if ($db_scheme eq 'mysql') {
789
                        $query = 'INSERT INTO ' . $table . ' (' . $fields . ') VALUES (' . $dataStr . ') ON DUPLICATE KEY UPDATE ' . $updateStr;
790
                    } else {
791
                        $query = 'INSERT INTO ' . $table . ' (' . $fields . ') VALUES (' . $dataStr . ')';
792
                    }
793
                    eval {
794
                        my $sth = $dbh->prepare($query);
795
                        if ($db_scheme eq 'mysql') {
796
                            $sth->execute((@$dataFieldsR, @$dataFieldsR));
797
                        } else {
798
                            $sth->execute(@$dataFieldsR);
799
                        }
800
                    };
801
                    if ($@) {
802
                        unless ($db_scheme eq 'mysql') {
803
                            $query = 'UPDATE ' . $table . ' SET ' . $updateStr . ' WHERE ';
804
                            map {$query .= $_ . '=? AND ';} @$PKArray;
805
                            $query = substr($query, 0, -4);
806
                            eval {
807
                                my $sth2 = $dbh->prepare($query);
808
                                my @dataPK = ();
809
                                map {push @dataPK, $dataFields->{$_};} @$PKArray;
810
                                $sth2->execute((@$dataFieldsR, @dataPK));
811
                            };
812
                            $ok = 1 unless ($@);
813
                        }
814
                        $debug and warn "Error _processRows_Table $@\n";
815
                    } else {
816
                        $ok = 1;
817
                    }
818
                    if ($ok) {
819
                        my $field = '';
820
                        map { $field .= $dataFields->{$_} . '_'; } @fieldsPK;
821
                        chop $field;
822
                        delete $fields2Delete->{$field} if (exists($fields2Delete->{$field}));
823
                    }
824
                    $ok = 0;
825
                }
826
            }
827
            $j++;
828
        }
829
        $nodeR = $nodeR->nextSibling;
830
    }
831
    return 1;
832
}#_processRows_Table
833
834
835
# Import worksheet from the ods content.xml file to the mysql table
836
sub _import_table_ods
837
{
838
    my ($dbh, $table, $frameworkcode, $dom, $PKArray, $fields2Delete) = @_;
839
    
840
    my $xc = XML::LibXML::XPathContext->new($dom);
841
    $xc->registerNs('xmlns:office','urn:oasis:names:tc:opendocument:xmlns:office:1.0');
842
    $xc->registerNs('xmlns:table','urn:oasis:names:tc:opendocument:xmlns:table:1.0');
843
    $xc->registerNs('xmlns:text','urn:oasis:names:tc:opendocument:xmlns:text:1.0');
844
    my @nodes;
845
    @nodes = $xc->findnodes('//table:table[@table:name="' . $table . '"]');
846
    if (@nodes == 1 && $nodes[0]->hasChildNodes()) {
847
        my $nodeR = $nodes[0]->firstChild;
848
        return _processRows_Table($dbh, $frameworkcode, $nodeR, $table, $PKArray, 'ods', $fields2Delete);
849
    } else {
850
        $debug and warn "Error _import_table_ods there's not worksheet for $table\n";
851
    }
852
    return 0;
853
}#_import_table_ods
854
855
856
# Import worksheet from the excel-xml file to the mysql table
857
sub _import_table_excel
858
{
859
    my ($dbh, $table, $frameworkcode, $dom, $PKArray, $fields2Delete) = @_;
860
    
861
    my $xc = XML::LibXML::XPathContext->new($dom);
862
    $xc->registerNs('xmlns','urn:schemas-microsoft-com:office:spreadsheet');
863
    $xc->registerNs('xmlns:ss','urn:schemas-microsoft-com:office:spreadsheet');
864
    $xc->registerNs('xmlns:x','urn:schemas-microsoft-com:office:excel');
865
    my @nodes;
866
    @nodes = $xc->findnodes('//ss:Worksheet[@ss:Name="' . $table . '"]');
867
    if (@nodes > 0) {
868
        for (my $i=0; $i < @nodes; $i++) {
869
            my @nodesT = $nodes[$i]->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Table');
870
            if (@nodesT == 1 && $nodesT[0]->hasChildNodes()) {
871
                my $nodeR = $nodesT[0]->firstChild;
872
                return _processRows_Table($dbh, $frameworkcode, $nodeR, $table, $PKArray, undef, $fields2Delete);
873
            }
874
        }
875
    } else {
876
        $debug and warn "Error _import_table_excel there's not worksheet for $table\n";
877
    }
878
    return 0;
879
}#_import_table_excel
880
881
882
# Get the data from a cell on a ods file through the value attribute or the text node
883
sub _getDataNodeODS
884
{
885
    my $node = shift;
886
887
    my $data;
888
    my $repeated = 0;
889
    if ($node->nodeType == 1 && $node->nodeName =~ /(?:table:)?table-cell/) {
890
        if ($node->hasAttributeNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'value')) {
891
            $data = $node->getAttributeNS('urn:oasis:names:tc:opendocument:xmlns:office:1.0', 'value');
892
        } elsif ($node->hasChildNodes()) {
893
            my @nodes2 = $node->getElementsByTagNameNS('urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'p');
894
            if (@nodes2 == 1 && $nodes2[0]->hasChildNodes()) {
895
                $data = $nodes2[0]->firstChild->nodeValue;
896
            }
897
        }
898
        if ($node->hasAttributeNS('urn:oasis:names:tc:opendocument:xmlns:table:1.0', 'number-columns-repeated')) {
899
            $repeated = $node->getAttributeNS('urn:oasis:names:tc:opendocument:xmlns:table:1.0', 'number-columns-repeated');
900
        }
901
    }
902
    return ($data, $repeated);
903
}#_getDataNodeODS
904
905
906
# Get the data from a row of a spreadsheet
907
sub _getDataFields
908
{
909
    my ($frameworkcode, $node, $fields, $format) = @_;
910
    
911
    my $dataFields = {};
912
    my @dataFieldsA = ();
913
    if ($node && $node->hasChildNodes()) {
914
        my $node2 = $node->firstChild;
915
        my ($data, $repeated);
916
        my $i = 0;
917
        my $ok = 0;
918
        $repeated = 0;
919
        while ($node2) {
920
            if ($format && $format eq 'ods') {
921
                ($data, $repeated) = _getDataNodeODS($node2) if ($repeated <= 0);
922
                $repeated--;
923
                $ok = 1 if (defined($data));
924
            } else {
925
                if ($node2->nodeType == 1 && $node2->nodeName  =~ /(?:ss:)?Cell/) {
926
                    my @nodes3 = $node2->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Data');
927
                    if (@nodes3 == 1 && $nodes3[0]->hasChildNodes()) {
928
                        $data = $nodes3[0]->firstChild->nodeValue;
929
                        $ok = 1;
930
                    }
931
                }
932
            }
933
            if ($ok) {
934
                $data = '' if ($data eq '#');
935
                $data = $frameworkcode if ($fields->[$i] eq 'frameworkcode');
936
                $dataFields->{$fields->[$i]} = $data;
937
                push @dataFieldsA, $data;
938
                $i++;
939
            }
940
            $ok = 0;
941
            $node2 = $node2->nextSibling if ($repeated <= 0);
942
        }
943
    }
944
    return ($dataFields, \@dataFieldsA);
945
}#_getDataFields
946
947
948
# Get the data from the first row to know the column names
949
sub _getFields
950
{
951
    my ($node, $fields, $format) = @_;
952
    
953
    if ($node && $node->hasChildNodes()) {
954
        my $node2 = $node->firstChild;
955
        my ($data, $repeated);
956
        while ($node2) {
957
            if ($format && $format eq 'ods') {
958
                ($data, $repeated) = _getDataNodeODS($node2);
959
                push @$fields, $data if (defined($data));
960
            } else {
961
                if ($node2->nodeType == 1 && $node2->nodeName =~ /(?:ss:)?Cell/) {
962
                    my @nodes3 = $node2->getElementsByTagNameNS('urn:schemas-microsoft-com:office:spreadsheet', 'Data');
963
                    if (@nodes3 == 1 && $nodes3[0]->hasChildNodes()) {
964
                        $data = $nodes3[0]->firstChild->nodeValue;
965
                        push @$fields, $data;
966
                    }
967
                }
968
            }
969
            $node2 = $node2->nextSibling;
970
        }
971
    }
972
}#_getFields
973
974
975
976
977
1;
978
__END__
979
980
=head1 AUTHOR
981
982
Koha Development Team <http://koha-community.org/>
983
984
=cut
985
986
(-)a/admin/import_export_framework.pl (+68 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2010-2011 MASmedios.com y Ministerio de Cultura
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
21
use strict;
22
use warnings;
23
use CGI;
24
use C4::Context;
25
use C4::ImportExportFramework;
26
27
my $input = new CGI;
28
29
my $frameworkcode = $input->param('frameworkcode') || '';
30
my $action = $input->param('action') || 'export';
31
32
## Exporting
33
if ($action eq 'export' && $input->request_method() eq 'GET') {
34
    my $strXml = '';
35
    ExportFramework($frameworkcode, \$strXml, $input->param('type_export_' . $frameworkcode));
36
    if ($input->param('type_export_' . $frameworkcode) eq 'excel') {
37
        # Excel-xml file
38
        print $input->header(-type => 'application/excel', -attachment => 'export_' . $frameworkcode . '.xml');
39
        print $strXml;
40
    } else {
41
        # ODS file
42
        my $strODS = '';
43
        createODS($strXml, 'en', \$strODS);
44
        print $input->header(-type => 'application/vnd.oasis.opendocument.spreadsheet', -attachment => 'export_' . $frameworkcode . '.ods');
45
        print $strODS;
46
    }
47
## Importing
48
} elsif ($input->request_method() eq 'POST') {
49
    my $ok = -1;
50
    my $fieldname = 'file_import_' . $frameworkcode;
51
    my $filename = $input->param($fieldname);
52
    # upload the input file
53
    if ($filename && $filename =~ /\.(ods|xml)$/i) {
54
        my $extension = $1;
55
        my $uploadFd = $input->upload($fieldname);
56
        if ($uploadFd && !$input->cgi_error) {
57
            my $tmpfilename = $input->tmpFileName($input->param($fieldname));
58
            $filename = $tmpfilename . '.' . $extension; # rename the tmp file with the extension
59
            $ok = ImportFramework($filename, $frameworkcode, 1) if (rename($tmpfilename, $filename));
60
        }
61
    }
62
    if ($ok >= 0) { # If everything went ok go to the framework marc structure
63
        print $input->redirect( -location => '/cgi-bin/koha/admin/marctagstructure.pl?frameworkcode=' . $frameworkcode);
64
    } else {
65
        # If something failed go to the list of frameworks and show message
66
        print $input->redirect( -location => '/cgi-bin/koha/admin/biblio_framework.pl?error_import_export=' . $frameworkcode);
67
    }
68
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css (+48 lines)
Lines 1924-1926 ul.budget_hierarchy li:first-child:after { Link Here
1924
	margin : 1em 0;
1924
	margin : 1em 0;
1925
}
1925
}
1926
fieldset.rows+h3 {clear:both;padding-top:.5em;}
1926
fieldset.rows+h3 {clear:both;padding-top:.5em;}
1927
1928
.import_export{
1929
    position:relative;
1930
}
1931
.import_export .import_export_options{
1932
    background: white;
1933
    border: 1px solid #CDCDCD;
1934
    left: 60px;
1935
    padding: 10px;
1936
    position: absolute;
1937
    top: 0;
1938
    z-index: 1;
1939
    width: 300px;
1940
}
1941
.import_export_options li{
1942
    display: block;
1943
    list-style: none;
1944
    padding-top: 10px;
1945
}
1946
.import_export_options .import_export_close {
1947
    cursor: pointer;
1948
    text-decoration: underline;
1949
}
1950
.import_export_options .export_ok {
1951
    padding: 10;
1952
    background: #E3E3E3 none;
1953
    cursor: pointer;
1954
    margin-left: 20px;
1955
    border: none;
1956
}
1957
.import_export_options .import_ok {
1958
    padding: 10;
1959
    background: #E3E3E3 none;
1960
    cursor: pointer;
1961
    margin-left: 20px;
1962
    border: none;
1963
}
1964
.form_import .input_import {
1965
    border: 1px solid #bcbcbc;
1966
}
1967
.import_export_options .importing {
1968
    padding: inherit;
1969
    background: none;
1970
}
1971
.li_close_import_export {
1972
    text-align: right;
1973
}
1974
 
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/biblio_framework.tmpl (-1 / +141 lines)
Lines 48-53 $(document).ready(function() { Link Here
48
});
48
});
49
//]]>
49
//]]>
50
</script>
50
</script>
51
<script type="text/javascript">
52
/* Import/Export from/to spreadsheet */
53
54
    var importing = false;
55
56
    $(document).ready(function() {
57
        $("body").css("cursor", "auto");
58
        $('.import_export_options').hide();
59
        $('a.import_export_fw').click(function() {
60
            if (!importing) {
61
                $('.import_export_options').hide();
62
                $(this).next().show('slide');
63
            }
64
            return false;
65
        });
66
        $('.import_export_close').click(function() {
67
            if (!importing) $('.import_export_options').fadeOut('fast');
68
        });
69
        $('.input_import').val("");
70
71
        var matches = new RegExp("\\?error_import_export=(.+)$").exec(window.location.search);
72
        if (matches && matches.length > 1) {
73
            alert("Error importing the framework " + decodeURIComponent(matches[1]));
74
        }
75
    });
76
    
77
    $(function() {
78
        $('input.input_import').change( function() {
79
            var filename = $(this).val();
80
            if ( ! /(?:\.ods|\.xml)$/.test(filename)) {
81
                $(this).css("background-color","yellow");
82
                try {
83
                    var pos = filename.lastIndexOf("/");
84
                    if (pos < 0) pos = filename.lastIndexOf("\\");
85
                    if (pos < 0) pos = filename.length;
86
                    var id = $(this).attr('id');
87
                    var obj = document.getElementById(id);
88
                    if (obj.setSelectionRange) {
89
                        obj.focus();
90
                        obj.setSelectionRange(pos * 2, filename.length * 2);
91
                    } else if (obj.createTextRange) {
92
                        var range = obj.createTextRange();
93
                        range.collapse(true);
94
                        range.moveEnd('character', filename.length * 2);
95
                        range.moveStart('character', pos);
96
                        range.select();
97
                    }
98
                } catch (e) {}
99
                alert('Please select an ods or xml file');
100
                $(this).val("");
101
                $(this).css("background-color","white");
102
            }
103
        });
104
        $('form.form_export').submit(function() {
105
            $('.import_export_options').hide();
106
            return true;
107
        });
108
        $('form.form_import').submit(function() {
109
            var id = $(this).attr('id');
110
            var obj = $('#' + id + ' input:file');
111
            if (/(?:\.ods|\.xml)$/.test(obj.val())) {
112
                if (confirm('Do you really want to import the framework fields/subfields (will overwrite current configuration, for safety reasons please make before an export to have a backup file)?')) {
113
                    var frameworkcode = $('#' + id + ' input:hidden[name=frameworkcode]').val();
114
                    $('#importing_' + frameworkcode).css('display', 'block');
115
                    if (navigator.userAgent.toLowerCase().indexOf('firefox') == -1) $("body").css("cursor", "progress");
116
                    importing = true;
117
                    return true;
118
                } else
119
                    return false;
120
            }
121
            obj.css("background-color","yellow");
122
            alert('Please select an ods or xml file');
123
            obj.val("");
124
            obj.css("background-color","white");
125
            return false;
126
        });
127
    });
128
    
129
    
130
131
</script>
132
51
</head>
133
</head>
52
<body>
134
<body>
53
<!-- TMPL_INCLUDE NAME="header.inc" -->
135
<!-- TMPL_INCLUDE NAME="header.inc" -->
Lines 115-120 $(document).ready(function() { Link Here
115
        <th>&nbsp;</th>
197
        <th>&nbsp;</th>
116
        <th>Edit</th>
198
        <th>Edit</th>
117
        <th>Delete</th>
199
        <th>Delete</th>
200
        <th title="Export framework structure (fields, subfields) to a spreadsheet file (.xml, .ods)">Export</th>
201
        <th title="Import framework structure (fields, subfields) from a spreadsheet file (.xml, .ods)">Import</th>
118
    </tr>
202
    </tr>
119
    <tr>
203
    <tr>
120
        <td>&nbsp;</td>
204
        <td>&nbsp;</td>
Lines 122-127 $(document).ready(function() { Link Here
122
        <td><a href="marctagstructure.pl?frameworkcode=<!-- TMPL_VAR NAME="frameworkcode" -->">MARC structure</a></td>
206
        <td><a href="marctagstructure.pl?frameworkcode=<!-- TMPL_VAR NAME="frameworkcode" -->">MARC structure</a></td>
123
        <td>&nbsp;</td>
207
        <td>&nbsp;</td>
124
        <td>&nbsp;</td>
208
        <td>&nbsp;</td>
209
        <td><div class="import_export"><a class="import_export_fw" href="#" title="Export <!-- TMPL_VAR NAME="frameworkcode" --> framework structure (fields, subfields) to a spreadsheet file (.xml, .ods)">Export</a>
210
            <div class="import_export_options">
211
                <form action="import_export_framework.pl" name="form_<!-- TMPL_VAR NAME="frameworkcode" -->" method="get" target="_blank"  class="form_export">
212
                    <input type="hidden" name="frameworkcode" value="<!-- TMPL_VAR NAME="frameworkcode" -->" />
213
                    <ul>
214
                        <li class="li_close_import_export"><span class="import_export_close" title="Close popup">Close</span></li>
215
                        <li><input type="radio" name="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" value="excel" id="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" checked="checked" /><label for="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" title="Export to Excel as xml format, compatible with OpenOffice/LibreOffice as well">Export to Excel with xml format</label></li>
216
                        <li><input type="radio" name="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" value="ods" id="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" /><label for="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->">Export to OpenDocument Spreadsheet format</label></li>
217
                        <li><input type="submit" class="export_ok" href="#" value="Export" title="Export to a spreadsheet" /></li>
218
                    </ul>
219
                </form>
220
            </div>
221
            </div>
222
        </td>
223
        <td><div class="import_export"><a href="#" class="import_export_fw" title="Import <!-- TMPL_VAR NAME="frameworkcode" --> framework structure (fields, subfields) from a spreadsheet file (.xml, .ods)">Import</a>
224
            <div class="import_export_options">
225
                <form action="/cgi-bin/koha/admin/import_export_framework.pl" name="form_i_<!-- TMPL_VAR NAME="frameworkcode" -->" id="form_i_<!-- TMPL_VAR NAME="frameworkcode" -->" method="post" enctype="multipart/form-data" class="form_import">
226
                    <input type="hidden" name="frameworkcode" value="<!-- TMPL_VAR NAME="frameworkcode" -->" />
227
                    <input type="hidden" name="action" value="import" />
228
                    <ul>
229
                        <li class="li_close_import_export"><span class="import_export_close" title="Close popup">Close</span></li>
230
                        <li><label for="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" title="Import from a spreadsheet, formats available: ods, xml (formatted from excel)">Spreadsheet file</label><input type="file" name="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" id="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" class="input_import" value="" autocomplete="off" /></li>
231
                        <li><input type="submit" class="import_ok" value="Import" title="Import from a spreadsheet" /><div id="importing_<!-- TMPL_VAR NAME="frameworkcode" -->" style="display:none" class="importing"><img src="/intranet-tmpl/prog/img/loading.gif" />Importing...</div></li>
232
                    </ul>
233
                </form>
234
            </div>
235
            </div>
236
        </td>
125
    </tr>
237
    </tr>
126
    <!-- note highlight assignment appears backwards because we already have a normal row for Default -->
238
    <!-- note highlight assignment appears backwards because we already have a normal row for Default -->
127
    <!-- TMPL_LOOP NAME="loop" -->
239
    <!-- TMPL_LOOP NAME="loop" -->
Lines 133-138 $(document).ready(function() { Link Here
133
            <td><a href="marctagstructure.pl?frameworkcode=<!-- TMPL_VAR name="frameworkcode" -->" >MARC structure</a></td>
245
            <td><a href="marctagstructure.pl?frameworkcode=<!-- TMPL_VAR name="frameworkcode" -->" >MARC structure</a></td>
134
            <td><a href="<!-- TMPL_VAR name="script_name" -->?op=add_form&amp;frameworkcode=<!-- TMPL_VAR name="frameworkcode" escape="HTML" -->">Edit</a></td>
246
            <td><a href="<!-- TMPL_VAR name="script_name" -->?op=add_form&amp;frameworkcode=<!-- TMPL_VAR name="frameworkcode" escape="HTML" -->">Edit</a></td>
135
            <td><a href="<!-- TMPL_VAR name="script_name" -->?op=delete_confirm&amp;frameworkcode=<!-- TMPL_VAR name="frameworkcode" escape="HTML" -->">Delete</a></td>
247
            <td><a href="<!-- TMPL_VAR name="script_name" -->?op=delete_confirm&amp;frameworkcode=<!-- TMPL_VAR name="frameworkcode" escape="HTML" -->">Delete</a></td>
248
            <td>
249
            <div class="import_export"><a class="import_export_fw" href="#" title="Export <!-- TMPL_VAR NAME="frameworkcode" --> framework structure (fields, subfields) to a spreadsheet file (.xml, .ods)">Export</a>
250
                <div class="import_export_options">
251
                    <form action="import_export_framework.pl" name="form_<!-- TMPL_VAR NAME="frameworkcode" -->" method="get" target="_blank" class="form_export">
252
                        <input type="hidden" name="frameworkcode" value="<!-- TMPL_VAR NAME="frameworkcode" -->" />
253
                        <ul>
254
                            <li class="li_close_import_export"><span class="import_export_close" title="Close popup">Close</span></li>
255
                            <li><input type="radio" name="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" value="excel" id="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" checked="checked" /><label for="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" title="Export to Excel as xml format, compatible with OpenOffice/LibreOffice as well">Export to Excel as xml format</label></li>
256
                            <li><input type="radio" name="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" value="ods" id="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->" /><label for="type_export_<!-- TMPL_VAR NAME="frameworkcode" -->">Export to OpenDocument Spreadsheet format</label></li>
257
                            <li><input type="submit" class="export_ok" href="#" value="Export" title="Export to a spreadsheet" /></li>
258
                        </ul>
259
                    </form>
260
                </div>
261
                </div>
262
            </td>
263
            <td><div class="import_export"><a class="import_export_fw" href="#" title="Import <!-- TMPL_VAR NAME="frameworkcode" --> framework structure (fields, subfields) from a spreadsheet file (.xml, .ods)">Import</a>
264
            <div class="import_export_options">
265
                <form action="/cgi-bin/koha/admin/import_export_framework.pl" name="form_i_<!-- TMPL_VAR NAME="frameworkcode" -->" id="form_i_<!-- TMPL_VAR NAME="frameworkcode" -->" method="post" enctype="multipart/form-data" class="form_import">
266
                    <input type="hidden" name="frameworkcode" value="<!-- TMPL_VAR NAME="frameworkcode" -->" />
267
                    <input type="hidden" name="action" value="import" />
268
                    <ul>
269
                        <li class="li_close_import_export"><span class="import_export_close" title="Close popup">Close</span></li>
270
                        <li><label for="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" title="Import from a spreadsheet, formats available: ods, xml (formatted from excel)">Spreadsheet file</label><input type="file" name="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" id="file_import_<!-- TMPL_VAR NAME="frameworkcode" -->" class="input_import" value="" autocomplete="off" /></li>
271
                        <li><input type="submit" class="import_ok" value="Import" title="Import from a spreadsheet" /><div id="importing_<!-- TMPL_VAR NAME="frameworkcode" -->" style="display:none" class="importing"><img src="/intranet-tmpl/prog/img/loading.gif" />Importing...</div></li>
272
                    </ul>
273
                </form>
274
            </div>
275
            </div>
276
        </td>
136
        </tr>
277
        </tr>
137
    <!-- /TMPL_LOOP -->
278
    <!-- /TMPL_LOOP -->
138
</table>
279
</table>
139
- 

Return to bug 5478