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

(-)a/C4/Biblio.pm (-17 / +62 lines)
Lines 42-48 use Koha::Caches; Link Here
42
use Koha::Authority::Types;
42
use Koha::Authority::Types;
43
use Koha::Acquisition::Currencies;
43
use Koha::Acquisition::Currencies;
44
use Koha::Biblio::Metadata;
44
use Koha::Biblio::Metadata;
45
use Koha::Biblio::DeletedMetadata;
45
use Koha::Biblio::Metadatas;
46
use Koha::Biblio::Metadatas;
47
use Koha::Biblio::DeletedMetadatas;
46
use Koha::SearchEngine;
48
use Koha::SearchEngine;
47
use Koha::Libraries;
49
use Koha::Libraries;
48
50
Lines 257-263 sub AddBiblio { Link Here
257
    _koha_marc_update_biblioitem_cn_sort( $record, $olddata, $frameworkcode );
259
    _koha_marc_update_biblioitem_cn_sort( $record, $olddata, $frameworkcode );
258
260
259
    # now add the record
261
    # now add the record
260
    ModBiblioMarc( $record, $biblionumber, $frameworkcode ) unless $defer_marc_save;
262
    ModBiblioMarc( $record, $biblionumber, $biblioitemnumber, $frameworkcode ) unless $defer_marc_save;
261
263
262
    # update OAI-PMH sets
264
    # update OAI-PMH sets
263
    if(C4::Context->preference("OAI-PMH:AutoUpdateSets")) {
265
    if(C4::Context->preference("OAI-PMH:AutoUpdateSets")) {
Lines 335-341 sub ModBiblio { Link Here
335
    _koha_marc_update_biblioitem_cn_sort( $record, $oldbiblio, $frameworkcode );
337
    _koha_marc_update_biblioitem_cn_sort( $record, $oldbiblio, $frameworkcode );
336
338
337
    # update the MARC record (that now contains biblio and items) with the new record data
339
    # update the MARC record (that now contains biblio and items) with the new record data
338
    &ModBiblioMarc( $record, $biblionumber, $frameworkcode );
340
    &ModBiblioMarc( $record, $biblionumber, $biblioitemnumber, $frameworkcode );
339
341
340
    # modify the other koha tables
342
    # modify the other koha tables
341
    _koha_modify_biblio( $dbh, $oldbiblio, $frameworkcode );
343
    _koha_modify_biblio( $dbh, $oldbiblio, $frameworkcode );
Lines 426-432 sub DelBiblio { Link Here
426
    $sth->execute($biblionumber);
428
    $sth->execute($biblionumber);
427
    while ( my $biblioitemnumber = $sth->fetchrow ) {
429
    while ( my $biblioitemnumber = $sth->fetchrow ) {
428
430
429
        # delete this biblioitem
431
        #Handle biblio_metadata and deletedbiblio_metadata first before biblioitems operations CASCADE there
432
        $error = _koha_delete_biblio_metadata( $dbh, $biblioitemnumber, $biblionumber );
433
        return $error if $error;
434
430
        $error = _koha_delete_biblioitems( $dbh, $biblioitemnumber );
435
        $error = _koha_delete_biblioitems( $dbh, $biblioitemnumber );
431
        return $error if $error;
436
        return $error if $error;
432
    }
437
    }
Lines 436-441 sub DelBiblio { Link Here
436
    # delete cascade will prevent deletedbiblioitems rows
441
    # delete cascade will prevent deletedbiblioitems rows
437
    # from being generated by _koha_delete_biblioitems
442
    # from being generated by _koha_delete_biblioitems
438
    $error = _koha_delete_biblio( $dbh, $biblionumber );
443
    $error = _koha_delete_biblio( $dbh, $biblionumber );
444
    return $error if $error;
439
445
440
    logaction( "CATALOGUING", "DELETE", $biblionumber, "biblio" ) if C4::Context->preference("CataloguingLog");
446
    logaction( "CATALOGUING", "DELETE", $biblionumber, "biblio" ) if C4::Context->preference("CataloguingLog");
441
447
Lines 1311-1317 sub GetMarcBiblio { Link Here
1311
    $sth->execute($biblionumber);
1317
    $sth->execute($biblionumber);
1312
    my $row     = $sth->fetchrow_hashref;
1318
    my $row     = $sth->fetchrow_hashref;
1313
    my $biblioitemnumber = $row->{'biblioitemnumber'};
1319
    my $biblioitemnumber = $row->{'biblioitemnumber'};
1314
    my $marcxml = GetXmlBiblio( $biblionumber );
1320
    my $marcxml = GetXmlBiblio( $biblioitemnumber );
1315
    $marcxml = StripNonXmlChars( $marcxml );
1321
    $marcxml = StripNonXmlChars( $marcxml );
1316
    my $frameworkcode = GetFrameworkCode($biblionumber);
1322
    my $frameworkcode = GetFrameworkCode($biblionumber);
1317
    MARC::File::XML->default_record_format( C4::Context->preference('marcflavour') );
1323
    MARC::File::XML->default_record_format( C4::Context->preference('marcflavour') );
Lines 1339-1363 sub GetMarcBiblio { Link Here
1339
1345
1340
=head2 GetXmlBiblio
1346
=head2 GetXmlBiblio
1341
1347
1342
  my $marcxml = GetXmlBiblio($biblionumber);
1348
  my $marcxml = GetXmlBiblio($biblioitemnumber);
1343
1349
1344
Returns biblio_metadata.metadata/marcxml of the biblionumber passed in parameter.
1350
Returns biblio_metadata.metadata/marcxml of the biblioitemnumber passed in parameter.
1345
The XML should only contain biblio information (item information is no longer stored in marcxml field)
1351
The XML should only contain biblio information (item information is no longer stored in marcxml field)
1346
1352
1347
=cut
1353
=cut
1348
1354
1349
sub GetXmlBiblio {
1355
sub GetXmlBiblio {
1350
    my ($biblionumber) = @_;
1356
    my ($biblioitemnumber, $biblionumber) = @_;
1351
    my $dbh = C4::Context->dbh;
1357
    my $dbh = C4::Context->dbh;
1352
    return unless $biblionumber;
1358
    return unless ($biblionumber || $biblioitemnumber);
1359
1360
    my @args;
1361
    my @pks;
1362
    if ($biblioitemnumber) {
1363
        push(@pks,  'biblioitemnumber = ?');
1364
        push(@args, $biblioitemnumber);
1365
    }
1366
    if ($biblionumber) {
1367
        push(@pks,  'biblionumber = ?');
1368
        push(@args, $biblionumber);
1369
    }
1353
    my ($marcxml) = $dbh->selectrow_array(
1370
    my ($marcxml) = $dbh->selectrow_array(
1354
        q|
1371
1355
        SELECT metadata
1372
        "SELECT metadata\n".
1356
        FROM biblio_metadata
1373
        "FROM biblio_metadata\n".
1357
        WHERE biblionumber=?
1374
        "WHERE\n".
1358
            AND format='marcxml'
1375
        "   ".join(" AND ", @pks)."\n".
1359
            AND marcflavour=?
1376
        "   AND format='marcxml'\n".
1360
    |, undef, $biblionumber, C4::Context->preference('marcflavour')
1377
        "   AND marcflavour=?\n"
1378
1379
        , undef, @args, C4::Context->preference('marcflavour')
1361
    );
1380
    );
1362
    return $marcxml;
1381
    return $marcxml;
1363
}
1382
}
Lines 3438-3448 sub _koha_delete_biblioitems { Link Here
3438
    return;
3457
    return;
3439
}
3458
}
3440
3459
3460
=head2 _koha_delete_biblio_metadata
3461
3462
  $error = _koha_delete_biblio_metadata($dbh, $biblioitemnumber, $biblionumber);
3463
3464
Internal sub for deleting from biblio_metadata table -- also saves to deletedbiblio_metadata
3465
3466
C<$dbh> - the database handle
3467
C<$biblioitemnumber> - the biblioitemnumber of the biblio_metadata to be deleted
3468
3469
=cut
3470
3471
# FIXME: add error handling
3472
3473
sub _koha_delete_biblio_metadata {
3474
    my ( $dbh, $biblioitemnumber ) = @_;
3475
3476
    my $m = Koha::Biblio::Metadatas->find({biblioitemnumber => $biblioitemnumber});
3477
    die "_koha_delete_biblio_metadata($biblioitemnumber):> No biblio_metadata-row!" unless $m;
3478
3479
    my $dm = Koha::Biblio::DeletedMetadata->new( $m->_result->{_column_data} );
3480
    $dm->store;
3481
    $m->delete();
3482
    return undef;
3483
}
3484
3441
=head1 UNEXPORTED FUNCTIONS
3485
=head1 UNEXPORTED FUNCTIONS
3442
3486
3443
=head2 ModBiblioMarc
3487
=head2 ModBiblioMarc
3444
3488
3445
  &ModBiblioMarc($newrec,$biblionumber,$frameworkcode);
3489
  &ModBiblioMarc($newrec,$biblionumber,$biblioitemnumber,$frameworkcode);
3446
3490
3447
Add MARC XML data for a biblio to koha
3491
Add MARC XML data for a biblio to koha
3448
3492
Lines 3453-3459 Function exported, but should NOT be used, unless you really know what you're do Link Here
3453
sub ModBiblioMarc {
3497
sub ModBiblioMarc {
3454
    # pass the MARC::Record to this function, and it will create the records in
3498
    # pass the MARC::Record to this function, and it will create the records in
3455
    # the marcxml field
3499
    # the marcxml field
3456
    my ( $record, $biblionumber, $frameworkcode ) = @_;
3500
    my ( $record, $biblionumber, $biblioitemnumber, $frameworkcode ) = @_;
3457
    if ( !$record ) {
3501
    if ( !$record ) {
3458
        carp 'ModBiblioMarc passed an undefined record';
3502
        carp 'ModBiblioMarc passed an undefined record';
3459
        return;
3503
        return;
Lines 3500-3505 sub ModBiblioMarc { Link Here
3500
    }
3544
    }
3501
3545
3502
    my $metadata = {
3546
    my $metadata = {
3547
        biblioitemnumber => $biblioitemnumber,
3503
        biblionumber => $biblionumber,
3548
        biblionumber => $biblionumber,
3504
        format       => 'marcxml',
3549
        format       => 'marcxml',
3505
        marcflavour  => C4::Context->preference('marcflavour'),
3550
        marcflavour  => C4::Context->preference('marcflavour'),
(-)a/C4/ImportBatch.pm (-1 / +1 lines)
Lines 663-669 sub BatchCommitRecords { Link Here
663
            my $oldxml;
663
            my $oldxml;
664
            if ($record_type eq 'biblio') {
664
            if ($record_type eq 'biblio') {
665
                my $oldbiblio = GetBiblio($recordid);
665
                my $oldbiblio = GetBiblio($recordid);
666
                $oldxml = GetXmlBiblio($recordid);
666
                $oldxml = GetXmlBiblio(undef, $recordid);
667
667
668
                # remove item fields so that they don't get
668
                # remove item fields so that they don't get
669
                # added again if record is reverted
669
                # added again if record is reverted
(-)a/Koha/Biblio/DeletedMetadata.pm (+32 lines)
Line 0 Link Here
1
package Koha::Biblio::DeletedMetadata;
2
3
# This file is part of Koha.
4
#
5
6
use Modern::Perl;
7
8
use Carp;
9
10
use Koha::Database;
11
12
use base qw(Koha::Object);
13
14
=head1 NAME
15
16
Koha::Biblio::DeletedMetadata - Koha Metadata Object class
17
18
=head1 API
19
20
=head2 Class Methods
21
22
=cut
23
24
=head3 type
25
26
=cut
27
28
sub _type {
29
    return 'DeletedbiblioMetadata';
30
}
31
32
1;
(-)a/Koha/Biblio/DeletedMetadatas.pm (+38 lines)
Line 0 Link Here
1
package Koha::Biblio::DeletedMetadatas;
2
3
# This file is part of Koha.
4
#
5
6
use Modern::Perl;
7
8
use Carp;
9
10
use Koha::Database;
11
12
use Koha::Biblio::Metadata;
13
14
use base qw(Koha::Objects);
15
16
=head1 NAME
17
18
Koha::Biblio::DeletedMetadatas - Koha Metadata Object set class
19
20
=head1 API
21
22
=head2 Class Methods
23
24
=cut
25
26
=head3 type
27
28
=cut
29
30
sub _type {
31
    return 'DeletedbiblioMetadata';
32
}
33
34
sub object_class {
35
    return 'Koha::Biblio::DeletedMetadata';
36
}
37
38
1;
(-)a/Koha/Biblio/Metadata.pm (-1 / +1 lines)
Lines 25-31 use base qw(Koha::Object); Link Here
25
25
26
=head1 NAME
26
=head1 NAME
27
27
28
Koha::Metadata - Koha Metadata Object class
28
Koha::Biblio::Metadata - Koha Metadata Object class
29
29
30
=head1 API
30
=head1 API
31
31
(-)a/Koha/BiblioUtils/Iterator.pm (-1 / +1 lines)
Lines 93-99 sub next { Link Here
93
    my $marc;
93
    my $marc;
94
    my $row = $self->{rs}->next();
94
    my $row = $self->{rs}->next();
95
    return if !$row;
95
    return if !$row;
96
    my $marcxml = C4::Biblio::GetXmlBiblio( $row->get_column('biblionumber') );
96
    my $marcxml = C4::Biblio::GetXmlBiblio( $row->get_column('biblioitemnumber') );
97
    if ( $marcxml ) {
97
    if ( $marcxml ) {
98
        $marc = MARC::Record->new_from_xml( $marcxml );
98
        $marc = MARC::Record->new_from_xml( $marcxml );
99
    }
99
    }
(-)a/Koha/Deletedbiblio.pm (+34 lines)
Line 0 Link Here
1
package Koha::Deletedbiblio;
2
3
# Copyright KohaSuomi 2017
4
#
5
# This file is part of Koha.
6
#
7
8
use Modern::Perl;
9
10
use Carp;
11
12
use Koha::Database;
13
14
use base qw(Koha::Object);
15
16
=head1 NAME
17
18
Koha::DeletedBiblio
19
20
=head1 API
21
22
=head2 Class Methods
23
24
=cut
25
26
=head3 type
27
28
=cut
29
30
sub _type {
31
    return 'Deletedbiblio';
32
}
33
34
1;
(-)a/Koha/Deletedbiblios.pm (+44 lines)
Line 0 Link Here
1
package Koha::Deletedbiblios;
2
3
# Copyright KohaSuomi 2017
4
#
5
# This file is part of Koha.
6
#
7
8
use Modern::Perl;
9
10
use Carp;
11
12
use Koha::Database;
13
14
use Koha::Deletedbiblio;
15
16
use base qw(Koha::Objects);
17
18
=head1 NAME
19
20
Koha::Deletedbiblios - Koha Biblio object set class
21
22
=head1 API
23
24
=head2 Class Methods
25
26
=cut
27
28
=head3 type
29
30
=cut
31
32
sub _type {
33
    return 'Deletedbiblio';
34
}
35
36
=head3 object_class
37
38
=cut
39
40
sub object_class {
41
    return 'Koha::Deletedbiblio';
42
}
43
44
1;
(-)a/installer/data/mysql/atomicupdate/Bug-18265-Followup_to_Buuug_17196.sql (+20 lines)
Line 0 Link Here
1
ALTER TABLE biblio_metadata DROP FOREIGN KEY `record_metadata_fk_1`;
2
ALTER TABLE biblio_metadata DROP KEY `biblio_metadata_uniq_key`;
3
ALTER TABLE biblio_metadata ADD COLUMN `biblioitemnumber` int(11) NOT NULL;
4
ALTER TABLE biblio_metadata ADD FOREIGN KEY `biblioitems_metadata_fk_1` (biblioitemnumber) REFERENCES biblioitems (biblioitemnumber) ON DELETE CASCADE ON UPDATE CASCADE;
5
ALTER TABLE biblio_metadata ADD UNIQUE KEY `biblio_metadata_uniq_key` (`biblioitemnumber`, `biblionumber`,`format`,`marcflavour`);
6
7
8
9
ALTER TABLE deletedbiblio_metadata DROP FOREIGN KEY `deletedrecord_metadata_fk_1`;
10
ALTER TABLE deletedbiblio_metadata DROP KEY `deletedbiblio_metadata_uniq_key`;
11
ALTER TABLE deletedbiblio_metadata ADD COLUMN `biblioitemnumber` int(11) NOT NULL;
12
## If this FK is preserved, most of the DelBiblio needs to be rewritten to gracefully
13
## move biblio and friends to deletedbiblio and deletedfriends without a chance for
14
## data loss in between.
15
## DelBiblio is implemented in a leaf-first way of handling the joint tables.
16
## You cannot INSERT leaf-first to deletedbiblio_metadata without the presence of deletedbiblioitems
17
#ALTER TABLE deletedbiblio_metadata ADD FOREIGN KEY `deletedbiblioitems_metadata_fk_1` (biblioitemnumber) REFERENCES deletedbiblioitems (biblioitemnumber) ON DELETE CASCADE ON UPDATE CASCADE;
18
ALTER TABLE deletedbiblio_metadata ADD UNIQUE KEY `deletedbiblio_metadata_uniq_key` (`biblioitemnumber`, `biblionumber`,`format`,`marcflavour`);
19
20
(-)a/misc/migration_tools/rebuild_zebra.pl (-1 / +1 lines)
Lines 495-501 sub export_marc_records_from_sth { Link Here
495
        print "\r$i" unless ($i++ %100 or !$verbose_logging);
495
        print "\r$i" unless ($i++ %100 or !$verbose_logging);
496
        if ( $nosanitize ) {
496
        if ( $nosanitize ) {
497
            my $marcxml = $record_type eq 'biblio'
497
            my $marcxml = $record_type eq 'biblio'
498
                          ? GetXmlBiblio( $record_number )
498
                          ? GetXmlBiblio( undef, $record_number )
499
                          : GetAuthorityXML( $record_number );
499
                          : GetAuthorityXML( $record_number );
500
            if ($record_type eq 'biblio'){
500
            if ($record_type eq 'biblio'){
501
                my @items = GetItemsInfo($record_number);
501
                my @items = GetItemsInfo($record_number);
(-)a/t/db_dependent/Biblio_crud.t (-1 / +111 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
5
use Modern::Perl;
6
use Test::More;
7
8
use C4::Biblio;
9
use Koha::Biblios;
10
use Koha::Deletedbiblios;
11
use Koha::Biblio::Metadatas;
12
use Koha::Biblio::DeletedMetadatas;
13
14
15
my $dbh = C4::Context->dbh;
16
# Start transaction
17
$dbh->{AutoCommit} = 0;
18
$dbh->{RaiseError} = 1;
19
20
21
##This test is not intended to fully cover all aspects of Biblio creation and it's linked business objects.
22
##It is simply intended for now to test biblio_metadata-table population.
23
subtest "Scenario: CRUD a Biblio, happy path", \&crudBiblio;
24
sub crudBiblio {
25
    my ($record, $kohaBiblio, $deletedKohaBiblio, $biblionumber, $biblioitemnumber, $metadata, $deletedMetadata);
26
    my $title = 'Incurable disease of test apparatuses';
27
    eval {
28
29
    $record = C4::Biblio::TransformKohaToMarc({
30
        'biblio.title'      => $title,
31
        'biblioitems.isbn'  => '0123456789',
32
    });
33
    ok($record,
34
        "Given a fresh Biblio from the top of my head");
35
36
37
    subtest "Create", sub {
38
39
        ($biblionumber, $biblioitemnumber) = C4::Biblio::AddBiblio($record,'');
40
        ok($biblionumber && $biblioitemnumber,
41
            "When the Biblio is added to DB");
42
    };
43
44
45
    subtest "Read", sub {
46
47
        $kohaBiblio = Koha::Biblios->find($biblionumber);
48
        ok($kohaBiblio,
49
            "Then it can be found from the DB");
50
51
        ok($kohaBiblio->biblionumber,
52
            "And it looks like a real biblio");
53
54
        $metadata = Koha::Biblio::Metadatas->find({biblioitemnumber => $biblioitemnumber});
55
        ok($metadata,
56
            "When I fetch the Metadata record from DB");
57
58
        is($metadata->format, 'marcxml',
59
            "Then the Metadata record format is 'marcxml'");
60
61
        is($metadata->biblionumber, $biblionumber,
62
            "And biblionumber matches the original Biblio");
63
64
        is($metadata->biblioitemnumber, $biblioitemnumber,
65
            "And the biblioitemnumber matches the original Biblio");
66
67
        #Shouldn't marcflavour be just flavour since we don't always store MARC to the biblio_metadata?
68
        is($metadata->marcflavour, C4::Context->preference("marcflavour"),
69
            "And the marcflavour is the default");
70
71
        like($metadata->metadata, qr/$title/,
72
            "And the record itself contains the correct title");
73
    };
74
75
76
    subtest "Delete", sub {
77
78
        ok(! C4::Biblio::DelBiblio($biblionumber),  #return value here doesnt matter. Should throw exceptions instead.
79
            "When I delete the Biblio");
80
81
        ok(! Koha::Biblios->find({biblionumber => $biblionumber}),
82
            "Then I get nothing when I fetch it from DB");
83
84
        $deletedKohaBiblio = Koha::Deletedbiblios->find({biblionumber => $biblionumber});
85
        ok($deletedKohaBiblio,
86
            "But I find it in the deletedbiblios");
87
88
        is($deletedKohaBiblio->title, $kohaBiblio->title,
89
            "And the Biblio looks just like before!");
90
91
        ok(! Koha::Biblio::Metadatas->find({biblioitemnumber => $biblioitemnumber}),
92
            "When I fetch the Metadata record, I get nothing");
93
94
        $deletedMetadata = Koha::Biblio::DeletedMetadatas->find({biblioitemnumber => $biblioitemnumber});
95
        ok($deletedMetadata,
96
            "But I found it in the deletedbiblio_metadata");
97
98
        is_deeply($deletedMetadata->_result->{_column_data}, $metadata->_result->{_column_data},
99
            "And the Metadata looks just like before!");
100
    };
101
102
    };
103
    ok(0, $@) if $@;
104
}
105
106
107
108
109
$dbh->rollback;
110
done_testing;
111

Return to bug 18265