1 package C4
::MarcModificationTemplates
;
3 # This file is part of Koha.
5 # Copyright 2010 Kyle M Hall <kyle.m.hall@gmail.com>
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
27 use vars
qw($VERSION @ISA @EXPORT);
29 use constant DEBUG => 0;
32 $VERSION = 1.00; # set the version for version checking
35 &GetModificationTemplates
36 &AddModificationTemplate
37 &DelModificationTemplate
39 &GetModificationTemplateAction
40 &GetModificationTemplateActions
42 &AddModificationTemplateAction
43 &ModModificationTemplateAction
44 &DelModificationTemplateAction
45 &MoveModificationTemplateAction
47 &ModifyRecordsWithTemplate
48 &ModifyRecordWithTemplate
55 C4::MarcModificationTemplates - Module to manage MARC Modification Templates
59 MARC Modification Templates are a tool for marc batch imports,
60 so that librarians can set up templates for various vendors'
61 files telling Koha what fields to insert data into.
67 =head2 GetModificationTemplates
69 my @templates = GetModificationTemplates( $template_id );
71 Passing optional $template_id marks it as the selected template.
75 sub GetModificationTemplates
{
76 my ( $template_id ) = @_;
77 warn("C4::MarcModificationTemplates::GetModificationTemplates( $template_id )") if DEBUG
;
79 my $dbh = C4
::Context
->dbh;
80 my $sth = $dbh->prepare("SELECT * FROM marc_modification_templates");
84 while ( my $template = $sth->fetchrow_hashref() ) {
85 $template->{'selected'} = 1
86 if $template_id && $template->{'template_id'} eq $template_id;
87 push( @templates, $template );
94 AddModificationTemplate
96 $template_id = AddModificationTemplate( $template_name[, $template_id ] );
98 If $template_id is supplied, the actions from that template will be copied
99 into the newly created template.
102 sub AddModificationTemplate
{
103 my ( $template_name, $template_id_copy ) = @_;
105 my $dbh = C4
::Context
->dbh;
106 my $sth = $dbh->prepare("INSERT INTO marc_modification_templates ( name ) VALUES ( ? )");
107 $sth->execute( $template_name );
109 $sth = $dbh->prepare("SELECT * FROM marc_modification_templates WHERE name = ?");
110 $sth->execute( $template_name );
111 my $row = $sth->fetchrow_hashref();
112 my $template_id = $row->{'template_id'};
114 if ( $template_id_copy ) {
115 my @actions = GetModificationTemplateActions
( $template_id_copy );
116 foreach my $action ( @actions ) {
117 AddModificationTemplateAction
(
120 $action->{'field_number'},
121 $action->{'from_field'},
122 $action->{'from_subfield'},
123 $action->{'field_value'},
124 $action->{'to_field'},
125 $action->{'to_subfield'},
126 $action->{'to_regex_search'},
127 $action->{'to_regex_replace'},
128 $action->{'to_regex_modifiers'},
129 $action->{'conditional'},
130 $action->{'conditional_field'},
131 $action->{'conditional_subfield'},
132 $action->{'conditional_comparison'},
133 $action->{'conditional_value'},
134 $action->{'conditional_regex'},
135 $action->{'description'},
145 DelModificationTemplate
147 DelModificationTemplate( $template_id );
150 sub DelModificationTemplate
{
151 my ( $template_id ) = @_;
153 my $dbh = C4
::Context
->dbh;
154 my $sth = $dbh->prepare("DELETE FROM marc_modification_templates WHERE template_id = ?");
155 $sth->execute( $template_id );
159 GetModificationTemplateAction
161 my $action = GetModificationTemplateAction( $mmta_id );
164 sub GetModificationTemplateAction
{
165 my ( $mmta_id ) = @_;
167 my $dbh = C4
::Context
->dbh;
168 my $sth = $dbh->prepare("SELECT * FROM marc_modification_template_actions WHERE mmta_id = ?");
169 $sth->execute( $mmta_id );
170 my $action = $sth->fetchrow_hashref();
176 GetModificationTemplateActions
178 my @actions = GetModificationTemplateActions( $template_id );
181 sub GetModificationTemplateActions
{
182 my ( $template_id ) = @_;
184 warn( "C4::MarcModificationTemplates::GetModificationTemplateActions( $template_id )" ) if DEBUG
;
186 my $dbh = C4
::Context
->dbh;
187 my $sth = $dbh->prepare("SELECT * FROM marc_modification_template_actions WHERE template_id = ? ORDER BY ordering");
188 $sth->execute( $template_id );
191 while ( my $action = $sth->fetchrow_hashref() ) {
192 push( @actions, $action );
195 warn( Data
::Dumper
::Dumper
( @actions ) ) if DEBUG
> 4;
201 AddModificationTemplateAction
203 AddModificationTemplateAction(
204 $template_id, $action, $field_number,
205 $from_field, $from_subfield, $field_value,
206 $to_field, $to_subfield, $to_regex_search, $to_regex_replace, $to_regex_modifiers
207 $conditional, $conditional_field, $conditional_subfield,
208 $conditional_comparison, $conditional_value,
209 $conditional_regex, $description
212 Adds a new action to the given modification template.
216 sub AddModificationTemplateAction
{
231 $conditional_subfield,
232 $conditional_comparison,
238 warn( "C4::MarcModificationTemplates::AddModificationTemplateAction( $template_id, $action,
239 $field_number, $from_field, $from_subfield, $field_value, $to_field, $to_subfield,
240 $to_regex_search, $to_regex_replace, $to_regex_modifiers, $conditional, $conditional_field, $conditional_subfield, $conditional_comparison,
241 $conditional_value, $conditional_regex, $description )" ) if DEBUG
;
243 $conditional_regex ||= '0';
245 my $dbh = C4
::Context
->dbh;
246 my $sth = $dbh->prepare( 'SELECT MAX(ordering) + 1 AS next_ordering FROM marc_modification_template_actions WHERE template_id = ?' );
247 $sth->execute( $template_id );
248 my $row = $sth->fetchrow_hashref;
249 my $ordering = $row->{'next_ordering'} || 1;
252 INSERT INTO marc_modification_template_actions (
268 conditional_subfield,
269 conditional_comparison,
274 VALUES ( NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";
276 $sth = $dbh->prepare( $query );
293 $conditional_subfield,
294 $conditional_comparison,
302 ModModificationTemplateAction
304 ModModificationTemplateAction(
305 $mmta_id, $action, $field_number, $from_field,
306 $from_subfield, $field_value, $to_field,
307 $to_subfield, $to_regex_search, $to_regex_replace, $to_regex_modifiers, $conditional,
308 $conditional_field, $conditional_subfield,
309 $conditional_comparison, $conditional_value,
310 $conditional_regex, $description
313 Modifies an existing action.
317 sub ModModificationTemplateAction
{
332 $conditional_subfield,
333 $conditional_comparison,
339 my $dbh = C4
::Context
->dbh;
342 UPDATE marc_modification_template_actions SET
351 to_regex_replace = ?,
352 to_regex_modifiers = ?,
354 conditional_field = ?,
355 conditional_subfield = ?,
356 conditional_comparison = ?,
357 conditional_value = ?,
358 conditional_regex = ?,
362 my $sth = $dbh->prepare( $query );
377 $conditional_subfield,
378 $conditional_comparison,
388 DelModificationTemplateAction
390 DelModificationTemplateAction( $mmta_id );
392 Deletes the given template action.
395 sub DelModificationTemplateAction
{
396 my ( $mmta_id ) = @_;
398 my $action = GetModificationTemplateAction
( $mmta_id );
400 my $dbh = C4
::Context
->dbh;
401 my $sth = $dbh->prepare("DELETE FROM marc_modification_template_actions WHERE mmta_id = ?");
402 $sth->execute( $mmta_id );
404 $sth = $dbh->prepare("UPDATE marc_modification_template_actions SET ordering = ordering - 1 WHERE template_id = ? AND ordering > ?");
405 $sth->execute( $action->{'template_id'}, $action->{'ordering'} );
409 MoveModificationTemplateAction
411 MoveModificationTemplateAction( $mmta_id, $where );
413 Changes the order for the given action.
414 Options for $where are 'up', 'down', 'top' and 'bottom'
416 sub MoveModificationTemplateAction
{
417 my ( $mmta_id, $where ) = @_;
419 my $action = GetModificationTemplateAction
( $mmta_id );
421 return if ( $action->{'ordering'} eq '1' && ( $where eq 'up' || $where eq 'top' ) );
422 return if ( $action->{'ordering'} eq GetModificationTemplateActions
( $action->{'template_id'} ) && ( $where eq 'down' || $where eq 'bottom' ) );
424 my $dbh = C4
::Context
->dbh;
427 if ( $where eq 'up' || $where eq 'down' ) {
429 ## For up and down, we just swap the ordering number with the one above or below it.
431 ## Change the ordering for the other action
432 $query = "UPDATE marc_modification_template_actions SET ordering = ? WHERE template_id = ? AND ordering = ?";
434 my $ordering = $action->{'ordering'};
435 $ordering-- if ( $where eq 'up' );
436 $ordering++ if ( $where eq 'down' );
438 $sth = $dbh->prepare( $query );
439 $sth->execute( $action->{'ordering'}, $action->{'template_id'}, $ordering );
441 ## Change the ordering for this action
442 $query = "UPDATE marc_modification_template_actions SET ordering = ? WHERE mmta_id = ?";
443 $sth = $dbh->prepare( $query );
444 $sth->execute( $ordering, $action->{'mmta_id'} );
446 } elsif ( $where eq 'top' ) {
448 $sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ordering + 1 WHERE template_id = ? AND ordering < ?');
449 $sth->execute( $action->{'template_id'}, $action->{'ordering'} );
451 $sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = 1 WHERE mmta_id = ?');
452 $sth->execute( $mmta_id );
454 } elsif ( $where eq 'bottom' ) {
456 my $ordering = GetModificationTemplateActions
( $action->{'template_id'} );
458 $sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ordering - 1 WHERE template_id = ? AND ordering > ?');
459 $sth->execute( $action->{'template_id'}, $action->{'ordering'} );
461 $sth = $dbh->prepare('UPDATE marc_modification_template_actions SET ordering = ? WHERE mmta_id = ?');
462 $sth->execute( $ordering, $mmta_id );
469 ModifyRecordsWithTemplate
471 ModifyRecordsWithTemplate( $template_id, $batch );
473 Accepts a template id and a MARC::Batch object.
476 sub ModifyRecordsWithTemplate
{
477 my ( $template_id, $batch ) = @_;
478 warn( "C4::MarcModificationTemplates::ModifyRecordsWithTemplate( $template_id, $batch )" ) if DEBUG
;
480 while ( my $record = $batch->next() ) {
481 ModifyRecordWithTemplate
( $template_id, $record );
486 ModifyRecordWithTemplate
488 ModifyRecordWithTemplate( $template_id, $record )
490 Accepts a MARC::Record object ( $record ) and modifies
491 it based on the actions for the given $template_id
494 sub ModifyRecordWithTemplate
{
495 my ( $template_id, $record ) = @_;
496 warn( "C4::MarcModificationTemplates::ModifyRecordWithTemplate( $template_id, $record )" ) if DEBUG
;
497 warn( "Unmodified Record:\n" . $record->as_formatted() ) if DEBUG
>= 10;
499 my $current_date = DateTime
->now()->ymd();
501 $branchcode = C4
::Context
->userenv->{branch
} if C4
::Context
->userenv;
503 my @actions = GetModificationTemplateActions
( $template_id );
505 foreach my $a ( @actions ) {
506 my $action = $a->{'action'};
507 my $field_number = $a->{'field_number'} // 1;
508 my $from_field = $a->{'from_field'};
509 my $from_subfield = $a->{'from_subfield'};
510 my $field_value = $a->{'field_value'};
511 my $to_field = $a->{'to_field'};
512 my $to_subfield = $a->{'to_subfield'};
513 my $to_regex_search = $a->{'to_regex_search'};
514 my $to_regex_replace = $a->{'to_regex_replace'};
515 my $to_regex_modifiers = $a->{'to_regex_modifiers'};
516 my $conditional = $a->{'conditional'};
517 my $conditional_field = $a->{'conditional_field'};
518 my $conditional_subfield = $a->{'conditional_subfield'};
519 my $conditional_comparison = $a->{'conditional_comparison'};
520 my $conditional_value = $a->{'conditional_value'};
521 my $conditional_regex = $a->{'conditional_regex'};
523 if ( $field_value ) {
524 $field_value =~ s/__CURRENTDATE__/$current_date/g;
525 $field_value =~ s/__BRANCHCODE__/$branchcode/g;
529 my $field_numbers = [];
530 if ( $conditional ) {
531 if ( $conditional_comparison eq 'exists' ) {
532 $field_numbers = field_exists
({
534 field
=> $conditional_field,
535 subfield
=> $conditional_subfield,
537 $do = $conditional eq 'if'
539 : not @
$field_numbers;
541 elsif ( $conditional_comparison eq 'not_exists' ) {
542 $field_numbers = field_exists
({
544 field
=> $conditional_field,
545 subfield
=> $conditional_subfield
547 $do = $conditional eq 'if'
548 ?
not @
$field_numbers
551 elsif ( $conditional_comparison eq 'equals' ) {
552 $field_numbers = field_equals
({
554 value
=> $conditional_value,
555 field
=> $conditional_field,
556 subfield
=> $conditional_subfield,
557 is_regex
=> $conditional_regex,
559 $do = $conditional eq 'if'
561 : not @
$field_numbers;
563 elsif ( $conditional_comparison eq 'not_equals' ) {
564 $field_numbers = field_equals
({
566 value
=> $conditional_value,
567 field
=> $conditional_field,
568 subfield
=> $conditional_subfield,
569 is_regex
=> $conditional_regex,
571 $do = $conditional eq 'if'
572 ?
not @
$field_numbers
579 # field_number == 0 if all field need to be updated
580 # or 1 if only the first field need to be updated
582 # A condition has been given
583 if ( @
$field_numbers > 0 ) {
584 if ( $field_number == 1 ) {
585 # We want only the first matching
586 $field_numbers = [ $field_numbers->[0] ];
589 # There was no condition
591 if ( $field_number == 1 ) {
592 # We want to process the first field
593 $field_numbers = [ 1 ];
594 } elsif ( $to_field and $from_field ne $to_field ) {
595 # If the from and to fields are not the same, we only process the first field.
596 $field_numbers = [ 1 ];
600 if ( $action eq 'copy_field' ) {
603 from_field
=> $from_field,
604 from_subfield
=> $from_subfield,
605 to_field
=> $to_field,
606 to_subfield
=> $to_subfield,
608 search
=> $to_regex_search,
609 replace
=> $to_regex_replace,
610 modifiers
=> $to_regex_modifiers
612 field_numbers
=> $field_numbers,
615 elsif ( $action eq 'update_field' ) {
618 field
=> $from_field,
619 subfield
=> $from_subfield,
620 values => [ $field_value ],
621 field_numbers
=> $field_numbers,
624 elsif ( $action eq 'move_field' ) {
627 from_field
=> $from_field,
628 from_subfield
=> $from_subfield,
629 to_field
=> $to_field,
630 to_subfield
=> $to_subfield,
632 search
=> $to_regex_search,
633 replace
=> $to_regex_replace,
634 modifiers
=> $to_regex_modifiers
636 field_numbers
=> $field_numbers,
639 elsif ( $action eq 'delete_field' ) {
642 field
=> $from_field,
643 subfield
=> $from_subfield,
644 field_numbers
=> $field_numbers,
649 warn( $record->as_formatted() ) if DEBUG
>= 10;