# CPAN modules
use DBI;
use Getopt::Long;
+use Encode qw( encode_utf8 );
# Koha modules
use C4::Context;
use C4::Installer;
use Koha::Database;
use Koha;
-use Koha::DateUtils;
+use Koha::DateUtils qw( dt_from_string output_pref );
use MARC::Record;
use MARC::File::XML ( BinaryEncoding => 'utf8' );
use File::Path qw[remove_tree]; # perl core module
-use File::Slurp;
# FIXME - The user might be installing a new database, so can't rely
# on /etc/koha.conf anyway.
my $schema = Koha::Database->new()->schema();
-my $silent;
+my ( $silent, $force );
GetOptions(
- 's' =>\$silent
- );
+ 's' => \$silent,
+ 'force' => \$force,
+);
my $dbh = C4::Context->dbh;
$|=1; # flushes output
[% IF checkout.auto_renew_error %]
The following item, [% biblio.title %], has not been renewed because:
[% IF checkout.auto_renew_error == 'too_many' %]
-You have reached the maximum number of checkouts possible.
+You have reached the maximum number of renewals possible.
[% ELSIF checkout.auto_renew_error == 'on_reserve' %]
This item is on hold for another patron.
[% ELSIF checkout.auto_renew_error == 'restriction' %]
for my $frameworkcode (@frameworkcodes) {
Koha::Caches->get_instance->clear_from_cache("MarcSubfieldStructure-$frameworkcode");
}
- Koha::Caches->get_instance->clear_from_cache("default_value_for_mod_marc-");
}
SetVersion( $DBversion );
value="batchmod,moredetail,cronjob,additem"
WHERE variable="MarkLostItemsAsReturned"
});
- } else {
+ } elsif ( $original_value == 0 || !defined($original_value) ) {
$dbh->do(q{
UPDATE systempreferences
SET type="multiple",
for my $order ( @$orders ) {
for my $claim (1..$order->{claims_count}) {
- $insert_claim_sth->execute($order->{ordernumber}, $order->{claimed_on});
+ $insert_claim_sth->execute($order->{ordernumber}, $order->{claimed_date});
}
}
UPDATE letter SET
name = REPLACE(name, "notification on auto renewing", "Notification of automatic renewal"),
title = REPLACE(title, "Auto renewals", "Automatic renewal notice"),
- content = REPLACE(content, "You have reach the maximum of checkouts possible.", "You have reached the maximum number of checkouts possible.")
+ content = REPLACE(content, "You have reach the maximum of checkouts possible.", "You have reached the maximum number of renewals possible.")
WHERE code = 'AUTO_RENEWALS';
});
$dbh->do(q{
if( CheckVersion( $DBversion ) ) {
# Adding the ON DELETE CASCASE ON UPDATE CASCADE, in case it's missing (from 9016 - 3.15.00.039)
+ if ( foreign_key_exists( 'letter', 'message_transport_type_fk' ) ) {
+ $dbh->do( q{
+ ALTER TABLE letter DROP FOREIGN KEY message_transport_type_fk
+ } );
+ }
$dbh->do( q{
- ALTER TABLE letter DROP FOREIGN KEY message_transport_type_fk
+ ALTER TABLE letter ADD CONSTRAINT message_transport_type_fk FOREIGN KEY (message_transport_type) REFERENCES message_transport_types(message_transport_type) ON DELETE CASCADE ON UPDATE CASCADE
} );
+ # Foreign keys should prevent this, however, it has been found in many production databases
$dbh->do( q{
- ALTER TABLE letter ADD CONSTRAINT message_transport_type_fk FOREIGN KEY (message_transport_type) REFERENCES message_transport_types(message_transport_type) ON DELETE CASCADE ON UPDATE CASCADE
+ DELETE borrower_message_transport_preferences FROM borrower_message_transport_preferences LEFT JOIN borrower_message_preferences USING (borrower_message_preference_id) WHERE borrower_message_preferences.borrower_message_preference_id IS NULL
} );
$dbh->do(q{
[% IF !checkout.auto_renew_error %]
was renewed until [% checkout.date_due | $KohaDates as_due_date => 1%]
[% ELSIF checkout.auto_renew_error == 'too_many' %]
- You have reached the maximum number of checkouts possible.
+ You have reached the maximum number of renewals possible.
[% ELSIF checkout.auto_renew_error == 'on_reserve' %]
This item is on hold for another patron.
[% ELSIF checkout.auto_renew_error == 'restriction' %]
$DBversion = '20.12.00.045';
if( CheckVersion( $DBversion ) ) {
$dbh->do(q{
- INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type) VALUES ('SearchLimitLibrary', 'both', 'homebranch|holdingbranch|both', "When limiting search results with a library or library group, use the item's home library, or holding library, or both.", 'Choice')
+ INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type) VALUES ('SearchLimitLibrary', 'homebranch', 'homebranch|holdingbranch|both', "When limiting search results with a library or library group, use the item's home library, or holding library, or both.", 'Choice')
});
NewVersion( $DBversion, 21249, "Adding new system preference SearchLimitLibrary" );
NewVersion( $DBversion, "", "Koha 21.05.00 release" );
}
-$DBversion = '21.06.00.000';
-if( CheckVersion( $DBversion ) ) {
- NewVersion( $DBversion, "", ["🎵 Run, rabbit run. 🎶", "Dig that hole, forget the sun,", "And when at last the work is done", "Don't sit down it's time to dig another one."] );
-}
-
-$DBversion = '21.06.00.001';
-if ( CheckVersion($DBversion) ) {
- $dbh->do('DELETE FROM sessions');
- $dbh->do('ALTER TABLE sessions MODIFY a_session LONGBLOB NOT NULL');
-
- NewVersion( $DBversion, '28489', 'Modify sessions.a_session from longtext to longblob' );
-}
-
-$DBversion = '21.06.00.002';
-if( CheckVersion( $DBversion ) ) {
- if( !column_exists( 'borrower_modifications', 'relationship' ) ) {
- $dbh->do(q{
- ALTER TABLE borrower_modifications ADD COLUMN `relationship` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `borrowernotes`
- });
- }
-
- if( !column_exists( 'borrowers', 'relationship' ) ) {
- $dbh->do(q{
- ALTER TABLE borrowers ADD COLUMN `relationship` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'used for children to include the relationship to their guarantor' AFTER `borrowernotes`
- });
- }
-
- if( !column_exists( 'deletedborrowers', 'relationship' ) ) {
- $dbh->do(q{
- ALTER TABLE deletedborrowers ADD COLUMN `relationship` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'used for children to include the relationship to their guarantor' AFTER `borrowernotes`
- });
- }
-
- NewVersion( $DBversion, 28490, "Bring back accidentally deleted relationship columns");
-}
-
-$DBversion = '21.06.00.003';
-if( CheckVersion( $DBversion ) ) {
-
- # Add 'WrongTransfer' to branchtransfers cancellation_reason enum
- $dbh->do(
- q{
- ALTER TABLE
- `branchtransfers`
- MODIFY COLUMN
- `cancellation_reason` enum(
- 'Manual',
- 'StockrotationAdvance',
- 'StockrotationRepatriation',
- 'ReturnToHome',
- 'ReturnToHolding',
- 'RotatingCollection',
- 'Reserve',
- 'LostReserve',
- 'CancelReserve',
- 'ItemLost',
- 'WrongTransfer'
- )
- AFTER `comments`
- }
- );
-
- NewVersion( $DBversion, 24434, "Add 'WrongTransfer' to branchtransfers.cancellation_reason enum");
-}
-
-$DBversion = '21.06.00.004';
-if ( CheckVersion($DBversion) ) {
-
- $dbh->do(q{
- INSERT IGNORE permissions (module_bit, code, description)
- VALUES
- (4, 'delete_borrowers', 'Delete borrowers')
- });
-
- $dbh->do(q{
- INSERT IGNORE INTO user_permissions (borrowernumber, module_bit, code)
- SELECT borrowernumber, 4, 'delete_borrowers' FROM user_permissions WHERE code = 'edit_borrowers'
- });
-
- NewVersion( $DBversion, 15788, "Split edit_borrowers permission" );
-}
-
-$DBversion = '21.06.00.005';
-if( CheckVersion( $DBversion ) ) {
- $dbh->do( q{
- INSERT IGNORE INTO systempreferences (variable, value, explanation, options, type)
- VALUES ('NewsLog', '0', 'If enabled, log OPAC News changes', '', 'YesNo')
- });
-
- NewVersion( $DBversion, 26205, "Add new system preference NewsLog to log news changes");
-}
-
-$DBversion = '21.06.00.006';
-if( CheckVersion( $DBversion ) ){
- unless( column_exists( 'course_items', 'biblionumber') ) {
- $dbh->do(q{ ALTER TABLE course_items ADD `biblionumber` int(11) AFTER `itemnumber` });
-
- $dbh->do(q{
- UPDATE course_items
- LEFT JOIN items ON items.itemnumber=course_items.itemnumber
- SET course_items.biblionumber=items.biblionumber
- WHERE items.itemnumber IS NOT NULL
- });
-
- $dbh->do(q{ ALTER TABLE course_items MODIFY COLUMN `biblionumber` INT(11) NOT NULL });
-
- $dbh->do(q{ ALTER TABLE course_items ADD CONSTRAINT `fk_course_items_biblionumber` FOREIGN KEY (`biblionumber`) REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE });
- $dbh->do(q{ ALTER TABLE course_items CHANGE `itemnumber` `itemnumber` int(11) DEFAULT NULL });
- }
-
- NewVersion( $DBversion, 14237, ["Add course_items.biblionumber column", "Add fk_course_items_biblionumber constraint", "Change course_items.itemnumber to allow NULL values"] );
-}
-
-$DBversion = '21.06.00.007';
-if( CheckVersion( $DBversion ) ) {
- if( !column_exists( 'borrowers', 'primary_contact_method' ) ) {
- $dbh->do( "ALTER TABLE `borrowers` ADD COLUMN `primary_contact_method` VARCHAR(45) DEFAULT NULL AFTER `autorenew_checkouts`" );
- }
-
- if( !column_exists( 'deletedborrowers', 'primary_contact_method' ) ) {
- $dbh->do( "ALTER TABLE `deletedborrowers` ADD COLUMN `primary_contact_method` VARCHAR(45) DEFAULT NULL AFTER `autorenew_checkouts`" );
- }
-
- if( !column_exists( 'borrower_modifications', 'primary_contact_method' ) ) {
- $dbh->do( "ALTER TABLE `borrower_modifications` ADD COLUMN `primary_contact_method` VARCHAR(45) DEFAULT NULL AFTER `gdpr_proc_consent`" );
- }
-
- NewVersion( $DBversion, 11879, "Add a new field to patron record: main contact method");
-}
-
-$DBversion = '21.06.00.008';
-if( CheckVersion( $DBversion ) ) {
- $dbh->do(q{
- INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
- ('ArticleRequestsOpacHostRedirection', '0', NULL, 'Enables redirection from child to host when requesting article on OPAC', 'YesNo')
- });
- NewVersion( $DBversion, 20310, "Add pref ArticleRequestsOpacHostRedirection");
-}
-
-$DBversion = '21.06.00.009';
-if( CheckVersion( $DBversion ) ) {
- unless ( column_exists('article_requests', 'format') ) {
- $dbh->do(q|
- ALTER TABLE article_requests
- ADD COLUMN `format` enum('PHOTOCOPY', 'SCAN') NOT NULL DEFAULT 'PHOTOCOPY' AFTER notes
- |);
- }
- unless ( column_exists('article_requests', 'urls') ) {
- $dbh->do(q|
- ALTER TABLE article_requests
- ADD COLUMN `urls` MEDIUMTEXT AFTER format
- |);
- }
- NewVersion( $DBversion, 20472, "Add columns format and urls in article_requests table");
-}
-
-$DBversion = '21.06.00.010';
-if( CheckVersion( $DBversion ) ) {
- $dbh->do(q{
- INSERT IGNORE INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `type` ) VALUES
- ('ArticleRequestsSupportedFormats', 'PHOTOCOPY', 'PHOTOCOPY|SCAN', 'List supported formats between vertical bars', 'free')
- });
- NewVersion( $DBversion, 20472, "Add syspref ArticleRequestsSupportedFormats");
-}
-
-$DBversion = '21.06.00.011';
-if( CheckVersion( $DBversion ) ) {
-
- my @fields = qw(
- branchname
- branchaddress1
- branchaddress2
- branchaddress3
- branchzip
- branchcity
- branchstate
- branchcountry
- branchphone
- branchfax
- branchemail
- branchillemail
- branchreplyto
- branchreturnpath
- branchurl
- branchip
- branchnotes
- opac_info
- marcorgcode
- );
- for my $f ( @fields ) {
- $dbh->do(qq{
- UPDATE branches
- SET $f = NULL
- WHERE $f = ""
- });
- }
-
- NewVersion( $DBversion, 28567, "Set to NULL empty branches fields");
-}
-
-$DBversion = '21.06.00.012';
-if( CheckVersion( $DBversion ) ) {
- if( !unique_key_exists( 'language_subtag_registry', 'uniq_lang' ) ) {
- $dbh->do(q{
- ALTER TABLE language_subtag_registry
- ADD UNIQUE KEY uniq_lang (subtag, type)
- });
- };
-
- if( !unique_key_exists( 'language_descriptions', 'uniq_desc' ) ) {
- $dbh->do(q{
- ALTER TABLE language_descriptions
- ADD UNIQUE KEY uniq_desc (subtag, type, lang)
- });
- };
-
- if( !unique_key_exists( 'language_rfc4646_to_iso639', 'uniq_code' ) ) {
- $dbh->do(q{
- ALTER TABLE language_rfc4646_to_iso639
- ADD UNIQUE KEY uniq_code (rfc4646_subtag, iso639_2_code)
- });
- };
-
- $dbh->do(q{
- INSERT IGNORE INTO language_subtag_registry (subtag, type, description, added)
- VALUES
- ('et', 'language', 'Estonian', now()),
- ('lv', 'language', 'Latvian', now()),
- ('lt', 'language', 'Lithuanian', now()),
- ('iu', 'language', 'Inuktitut', now()),
- ('ik', 'language', 'Inupiaq', now())
- });
-
- $dbh->do(q{
- INSERT IGNORE INTO language_descriptions (subtag, type, lang, description)
- VALUES
- ('et', 'language', 'en', 'Estonian'),
- ('et', 'language', 'et', 'Eesti'),
- ('lv', 'language', 'en', 'Latvian'),
- ('lv', 'language', 'lv', 'Latvija'),
- ('lt', 'language', 'en', 'Lithuanian'),
- ('lt', 'language', 'lt', 'Lietuvių'),
- ('iu', 'language', 'en', 'Inuktitut'),
- ('iu', 'language', 'iu', 'ᐃᓄᒃᑎᑐᑦ'),
- ('ik', 'language', 'en', 'Inupiaq'),
- ('ik', 'language', 'ik', 'Iñupiaq')
- });
-
- $dbh->do(q{
- INSERT IGNORE INTO language_rfc4646_to_iso639 (rfc4646_subtag, iso639_2_code)
- VALUES
- ('et', 'est'),
- ('lv', 'lav'),
- ('lt', 'lit'),
- ('iu', 'iku'),
- ('ik', 'ipk')
- });
-
- NewVersion( $DBversion, 15067, "Add missing languages" );
-}
+unless ( $ENV{HTTP_HOST} ) { # Is that correct?
+ my $files = get_db_entries;
+ my $report = update( $files, { force => $force } );
-$DBversion = '21.06.00.013';
-if( CheckVersion( $DBversion ) ) {
- # Remove foreign key for offset types
- if ( foreign_key_exists( 'account_offsets', 'account_offsets_ibfk_t' ) ) {
- $dbh->do( "ALTER TABLE account_offsets DROP FOREIGN KEY account_offsets_ibfk_t" );
+ for my $s ( @{ $report->{success} } ) {
+ say Encode::encode_utf8(join "\n", @{$s->{output}});
}
-
- # Drop account_offset_types table
- $dbh->do( "DROP TABLE IF EXISTS account_offset_types" );
-
- # Update offset_types to 'CREATE' where appropriate
- $dbh->do( "UPDATE account_offsets SET type = 'CREATE' WHERE type != 'OVERDUE_INCREASE' AND type != 'OVERDUE_DECREASE' AND ( debit_id IS NULL OR credit_id IS NULL)" );
- $dbh->do( "UPDATE account_offsets SET amount = ABS(amount) WHERE type = 'CREATE'" );
-
- # Update offset_types to 'APPLY' where appropriate
- $dbh->do( "UPDATE account_offsets SET type = 'APPLY' WHERE type != 'OVERDUE_INCREASE' AND type != 'OVERDUE_DECREASE' AND type != 'CREATE' AND type != 'VOID'" );
-
- # Update table to ENUM
- $dbh->do(
- q{
- ALTER TABLE
- `account_offsets`
- MODIFY COLUMN
- `type` enum(
- 'CREATE',
- 'APPLY',
- 'VOID',
- 'OVERDUE_INCREASE',
- 'OVERDUE_DECREASE'
- )
- AFTER `debit_id`
- }
- );
-
-
- NewVersion( $DBversion, 22435, "Update existing offsets");
-}
-
-$DBversion = '21.06.00.014';
-if( CheckVersion( $DBversion ) ) {
- if ( column_exists('message_queue', 'delivery_note') ) {
- $dbh->do(q{
- ALTER TABLE message_queue CHANGE COLUMN delivery_note failure_code MEDIUMTEXT
- });
+ for my $e ( @{ $report->{error} } ) {
+ say Encode::encode_utf8(join "\n", @{$e->{output}});
+ say Encode::encode_utf8("ERROR - " . $e->{error});
}
- if( !column_exists( 'message_queue', 'failure_code' ) ) {
- $dbh->do(q{
- ALTER TABLE message_queue ADD failure_code mediumtext AFTER content_type
- });
+ my $atomic_update_files = get_atomic_updates;
+ $report = run_atomic_updates($atomic_update_files);
+ for my $s ( @{ $report->{success} } ) {
+ say Encode::encode_utf8(join "\n", @{$s->{output}});
}
-
- NewVersion( $DBversion, 28813, "Update delivery_note to failure_code in message_queue");
-}
-
-# SEE bug 13068
-# if there is anything in the atomicupdate, read and execute it.
-my $update_dir = C4::Context->config('intranetdir') . '/installer/data/mysql/atomicupdate/';
-opendir( my $dirh, $update_dir );
-foreach my $file ( sort readdir $dirh ) {
- next if $file !~ /\.(sql|perl)$/; #skip other files
- next if $file eq 'skeleton.perl'; # skip the skeleton file
- print "DEV atomic update: $file\n";
- if ( $file =~ /\.sql$/ ) {
- my $installer = C4::Installer->new();
- my $rv = $installer->load_sql( $update_dir . $file ) ? 0 : 1;
- } elsif ( $file =~ /\.perl$/ ) {
- my $code = read_file( $update_dir . $file );
- eval $code; ## no critic (StringyEval)
- say "Atomic update generated errors: $@" if $@;
+ for my $e ( @{ $report->{error} } ) {
+ say Encode::encode_utf8(join "\n", @{$e->{output}});
+ say Encode::encode_utf8("ERROR - " . $e->{error});
}
-}
-
-=head1 FUNCTIONS
-=head2 DropAllForeignKeys($table)
-Drop all foreign keys of the table $table
-
-=cut
-
-sub DropAllForeignKeys {
- my ($table) = @_;
- # get the table description
- my $sth = $dbh->prepare("SHOW CREATE TABLE $table");
- $sth->execute;
- my $vsc_structure = $sth->fetchrow;
- # split on CONSTRAINT keyword
- my @fks = split /CONSTRAINT /,$vsc_structure;
- # parse each entry
- foreach (@fks) {
- # isolate what is before FOREIGN KEY, if there is something, it's a foreign key to drop
- $_ = /(.*) FOREIGN KEY.*/;
- my $id = $1;
- if ($id) {
- # we have found 1 foreign, drop it
- $dbh->do("ALTER TABLE $table DROP FOREIGN KEY $id");
- $id="";
- }
- }
-}
-
-
-=head2 TransformToNum
-
-Transform the Koha version from a 4 parts string
-to a number, with just 1 .
-
-=cut
-
-sub TransformToNum {
- my $version = shift;
- # remove the 3 last . to have a Perl number
- $version =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
- # three X's at the end indicate that you are testing patch with dbrev
- # change it into 999
- # prevents error on a < comparison between strings (should be: lt)
- $version =~ s/XXX$/999/;
- return $version;
-}
-
-=head2 SetVersion
-
-set the DBversion in the systempreferences
-
-=cut
-
-sub SetVersion {
- return if $_[0]=~ /XXX$/;
- #you are testing a patch with a db revision; do not change version
- my $kohaversion = TransformToNum($_[0]);
- if (C4::Context->preference('Version')) {
- my $finish=$dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='Version'");
- $finish->execute($kohaversion);
- } else {
- my $finish=$dbh->prepare("INSERT into systempreferences (variable,value,explanation) values ('Version',?,'The Koha database version. WARNING: Do not change this value manually, it is maintained by the webinstaller')");
- $finish->execute($kohaversion);
- }
- C4::Context::clear_syspref_cache(); # invalidate cached preferences
-}
-
-sub NewVersion {
- my ( $DBversion, $bug_number, $descriptions ) = @_;
-
- SetVersion($DBversion);
-
- unless ( ref($descriptions) ) {
- $descriptions = [ $descriptions ];
- }
- my $first = 1;
- my $time = POSIX::strftime("%H:%M:%S",localtime);
- for my $description ( @$descriptions ) {
- if ( @$descriptions > 1 ) {
- if ( $first ) {
- unless ( $bug_number ) {
- say sprintf "Upgrade to %s done [%s]: %s", $DBversion, $time, $description;
- } else {
- say sprintf "Upgrade to %s done [%s]: Bug %5s - %s", $DBversion, $time, $bug_number, $description;
- }
- } else {
- say sprintf "\t\t\t\t\t\t - %s", $description;
- }
- } else {
- unless ( $bug_number ) {
- say sprintf "Upgrade to %s done [%s]: %s", $DBversion, $time, $description;
- } else {
- say sprintf "Upgrade to %s done [%s]: Bug %5s - %s", $DBversion, $time, $bug_number, $description;
- }
- }
- $first = 0;
- }
-}
-
-=head2 CheckVersion
-
-Check whether a given update should be run when passed the proposed version
-number. The update will always be run if the proposed version is greater
-than the current database version and less than or equal to the version in
-kohaversion.pl. The update is also run if the version contains XXX, though
-this behavior will be changed following the adoption of non-linear updates
-as implemented in bug 7167.
-
-=cut
-
-sub CheckVersion {
- my ($proposed_version) = @_;
- my $version_number = TransformToNum($proposed_version);
-
- # The following line should be deleted when bug 7167 is pushed
- return 1 if ( $proposed_version =~ m/XXX/ );
-
- if ( C4::Context->preference("Version") < $version_number
- && $version_number <= TransformToNum( $Koha::VERSION ) )
- {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-sub sanitize_zero_date {
- my ( $table_name, $column_name ) = @_;
-
- my (undef, $datatype) = $dbh->selectrow_array(qq|
- SHOW COLUMNS FROM $table_name WHERE Field = ?|, undef, $column_name);
-
- if ( $datatype eq 'date' ) {
- $dbh->do(qq|
- UPDATE $table_name
- SET $column_name = NULL
- WHERE CAST($column_name AS CHAR(10)) = '0000-00-00';
- |);
- } else {
- $dbh->do(qq|
- UPDATE $table_name
- SET $column_name = NULL
- WHERE CAST($column_name AS CHAR(19)) = '0000-00-00 00:00:00';
- |);
- }
}
exit;