17 changed files with 99 additions and 1297 deletions
@ -1,554 +0,0 @@ |
|||
package C4::Update::Database; |
|||
|
|||
# Copyright Biblibre 2012 |
|||
# |
|||
# This file is part of Koha. |
|||
# |
|||
# Koha is free software; you can redistribute it and/or modify it under the |
|||
# terms of the GNU General Public License as published by the Free Software |
|||
# Foundation; either version 2 of the License, or (at your option) any later |
|||
# version. |
|||
# |
|||
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
|||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
|||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License along |
|||
# with Koha; if not, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use C4::Context; |
|||
|
|||
use File::Basename; |
|||
use File::Find::Rule; |
|||
use Digest::MD5; |
|||
use List::MoreUtils qw/uniq/; |
|||
use YAML; |
|||
|
|||
=head1 NAME |
|||
|
|||
C4::Update::Database.pm |
|||
|
|||
=head1 SYNOPSIS |
|||
|
|||
use C4::Update::Database; |
|||
|
|||
This package is used by admin/updatedatabase.pl, to manage DB updates |
|||
|
|||
=head1 FUNCTIONS |
|||
|
|||
=cut |
|||
|
|||
my $VERSIONS_PATH = C4::Context->config('intranetdir') . '/installer/data/mysql/versions'; |
|||
|
|||
my $version; |
|||
my $list; |
|||
|
|||
my $dbh = C4::Context->dbh; |
|||
|
|||
=head2 get_filepath |
|||
|
|||
my $file = get_filepath($version); |
|||
this sub will return the full path of a given DB update number |
|||
|
|||
=cut |
|||
|
|||
sub get_filepath { |
|||
my ( $version ) = @_; |
|||
my @files = File::Find::Rule->file->name( "$version.sql", "$version.pl" ) ->in( ( $VERSIONS_PATH ) ); |
|||
|
|||
if ( scalar @files != 1 ) { |
|||
die "This version ($version) returned has ".scalar @files." corresponding, need only 1"; |
|||
} |
|||
|
|||
return $files[0]; |
|||
} |
|||
|
|||
=head2 get_md5 |
|||
|
|||
my $md5 = get_md5($filepath) |
|||
returns the md5sum of the selected file. |
|||
This is used to check consistency of updates |
|||
|
|||
=cut |
|||
|
|||
sub get_md5 { |
|||
my ( $filepath ) = @_; |
|||
open(FILE, $filepath); |
|||
|
|||
my $ctx = Digest::MD5->new; |
|||
$ctx->addfile(*FILE); |
|||
my $md5 = $ctx->hexdigest; |
|||
close(FILE); |
|||
return $md5; |
|||
} |
|||
|
|||
=head2 execute_version |
|||
|
|||
$result = execute_version($version_number); |
|||
Execute an update. |
|||
This sub will detect if the number is made through a .pl or a .sql, and behave accordingly |
|||
if there is more than 1 file with the same number, an error will be issued |
|||
if you try to execute a version_number that has already be executed, then it will also issue an error |
|||
the sub return an result hash, with the version number and the result |
|||
|
|||
=cut |
|||
|
|||
sub execute_version { |
|||
my ( $version ) = @_; |
|||
my $report; |
|||
|
|||
my $filepath; |
|||
eval { |
|||
$filepath = get_filepath $version; |
|||
}; |
|||
if ( $@ ) { |
|||
return { $version => $@ }; |
|||
} |
|||
|
|||
my @file_infos = fileparse( $filepath, qr/\.[^.]*/ ); |
|||
my $extension = $file_infos[2]; |
|||
my $filename = $version . $extension; |
|||
|
|||
my $md5 = get_md5 $filepath; |
|||
my $r = md5_already_exists( $md5 ); |
|||
if ( scalar @$r ) { |
|||
my $p = @$r[0]; |
|||
$report->{$version} = { |
|||
error => "ALREADY_EXISTS", |
|||
filepath => $filepath, |
|||
old_version => @$r[0]->{version}, |
|||
md5 => @$r[0]->{md5}, |
|||
}; |
|||
return $report; |
|||
} |
|||
|
|||
my $queries; |
|||
given ( $extension ) { |
|||
when ( /.sql/ ) { |
|||
$queries = get_queries ( $filepath ); |
|||
} |
|||
when ( /.pl/ ) { |
|||
eval { |
|||
$queries = get_queries ( $filepath ); |
|||
}; |
|||
if ($@) { |
|||
$report->{$version} = { |
|||
error => "LOAD_FUNCTIONS_FAILED", |
|||
filename => $filename, |
|||
error_str => $@, |
|||
}; |
|||
} |
|||
} |
|||
default { |
|||
$report->{$version} = { |
|||
error => "BAD_EXTENSION", |
|||
extension => $extension, |
|||
}; |
|||
} |
|||
} |
|||
|
|||
return $report |
|||
if ( defined $report->{$version} ); |
|||
|
|||
my $errors = execute ( $queries ); |
|||
$report->{$version} = scalar( @$errors ) ? $errors : "OK"; |
|||
set_infos ( $version, $queries, $errors, $md5 ); |
|||
return $report; |
|||
} |
|||
|
|||
=head2 list_versions_available |
|||
|
|||
my @versions = list_versions_available; |
|||
return an array with all version available |
|||
|
|||
=cut |
|||
|
|||
sub list_versions_available { |
|||
my @versions; |
|||
|
|||
my @files = File::Find::Rule->file->name( "*.sql", "*.pl" ) ->in( ( $VERSIONS_PATH ) ); |
|||
|
|||
for my $f ( @files ) { |
|||
my @file_infos = fileparse( $f, qr/\.[^.]*/ ); |
|||
push @versions, $file_infos[0]; |
|||
} |
|||
@versions = uniq @versions; |
|||
return \@versions; |
|||
} |
|||
|
|||
=head2 list_versions_already_applied |
|||
|
|||
my @versions = list_versions_available; |
|||
return an array with all version that have already been applied |
|||
This sub check first that the updatedb tables exist and create them if needed |
|||
|
|||
=cut |
|||
|
|||
sub list_versions_already_applied { |
|||
# 1st check if tables exist, otherwise create them |
|||
$dbh->do(qq{ |
|||
CREATE TABLE IF NOT EXISTS `updatedb_error` ( `version` varchar(32) DEFAULT NULL, `error` text ) ENGINE=InnoDB CHARSET=utf8; |
|||
}); |
|||
$dbh->do(qq{ |
|||
CREATE TABLE IF NOT EXISTS `updatedb_query` ( `version` varchar(32) DEFAULT NULL, `query` text ) ENGINE=InnoDB CHARSET=utf8; |
|||
}); |
|||
$dbh->do(qq{ |
|||
CREATE TABLE IF NOT EXISTS `updatedb_report` ( `version` text, `md5` varchar(50) DEFAULT NULL, `comment` text, `status` int(1) DEFAULT NULL ) ENGINE=InnoDB CHARSET=utf8; |
|||
}); |
|||
|
|||
my $query = qq/ SELECT version, comment, status FROM updatedb_report ORDER BY version/; |
|||
my $sth = $dbh->prepare( $query ); |
|||
$sth->execute; |
|||
my $versions = $sth->fetchall_arrayref( {} ); |
|||
map { |
|||
my $version = $_; |
|||
my @comments = defined $_->{comment} ? split '\\\n', $_->{comment} : ""; |
|||
push @{ $version->{comments} }, { comment => $_ } for @comments; |
|||
delete $version->{comment}; |
|||
} @$versions; |
|||
$sth->finish; |
|||
for my $version ( @$versions ) { |
|||
$query = qq/ SELECT query FROM updatedb_query WHERE version = ? ORDER BY version/; |
|||
$sth = $dbh->prepare( $query ); |
|||
$sth->execute( $version->{version} ); |
|||
$version->{queries} = $sth->fetchall_arrayref( {} ); |
|||
$sth->finish; |
|||
$query = qq/ SELECT error FROM updatedb_error WHERE version = ? ORDER BY version/; |
|||
$sth = $dbh->prepare( $query ); |
|||
$sth->execute( $version->{version} ); |
|||
$version->{errors} = $sth->fetchall_arrayref( {} ); |
|||
$sth->finish; |
|||
} |
|||
return $versions; |
|||
} |
|||
|
|||
=head2 execute |
|||
|
|||
my @errors = $execute(\@queries); |
|||
This sub will execute queries coming from an execute_version based on a .sql file |
|||
|
|||
=cut |
|||
|
|||
sub execute { |
|||
my ( $queries ) = @_; |
|||
my @errors; |
|||
for my $query ( @{$queries->{queries}} ) { |
|||
eval { |
|||
$dbh->do( $query ); |
|||
}; |
|||
push @errors, get_error(); |
|||
} |
|||
return \@errors; |
|||
} |
|||
|
|||
=head2 get_tables_name |
|||
|
|||
my $tables = get_tables_name; |
|||
return an array with all Koha mySQL table names |
|||
|
|||
=cut |
|||
|
|||
sub get_tables_name { |
|||
my $sth = $dbh->prepare("SHOW TABLES"); |
|||
$sth->execute(); |
|||
my @tables; |
|||
while ( my ( $table ) = $sth->fetchrow_array ) { |
|||
push @tables, $table; |
|||
} |
|||
return \@tables; |
|||
} |
|||
my $tables; |
|||
|
|||
=head2 check_coherency |
|||
|
|||
my $errors = check_coherency($query); UNUSED |
|||
This sub will try to check if a SQL query is useless or no. |
|||
for queries that are CREATE TABLE, it will check if the table already exists |
|||
for queries that are ALTER TABLE, it will search if the modification has already been made |
|||
for queries that are INSERT, it will search if the insert has already been made if it's a syspref or a permission |
|||
|
|||
Those test cover 90% of the updatedatabases cases. That will help finding duplicate or inconsistencies |
|||
|
|||
=cut |
|||
|
|||
#sub check_coherency { |
|||
# my ( $query ) = @_; |
|||
# $tables = get_tables_name() if not $tables; |
|||
# |
|||
# given ( $query ) { |
|||
# when ( /CREATE TABLE(?:.*?)? `?(\w+)`?/ ) { |
|||
# my $table_name = $1; |
|||
# if ( grep { /$table_name/ } @$tables ) { |
|||
# die "COHERENCY: Table $table_name already exists"; |
|||
# } |
|||
# } |
|||
# |
|||
# when ( /ALTER TABLE *`?(\w+)`? *ADD *(?:COLUMN)? `?(\w+)`?/ ) { |
|||
# my $table_name = $1; |
|||
# my $column_name = $2; |
|||
# next if $column_name =~ /(UNIQUE|CONSTRAINT|INDEX|KEY|FOREIGN)/; |
|||
# if ( not grep { /$table_name/ } @$tables ) { |
|||
# return "COHERENCY: Table $table_name does not exist"; |
|||
# } else { |
|||
# my $sth = $dbh->prepare( "DESC $table_name $column_name" ); |
|||
# my $rv = $sth->execute; |
|||
# if ( $rv > 0 ) { |
|||
# die "COHERENCY: Field $table_name.$column_name already exists"; |
|||
# } |
|||
# } |
|||
# } |
|||
# |
|||
# when ( /INSERT INTO `?(\w+)`?.*?VALUES *\((.*?)\)/ ) { |
|||
# my $table_name = $1; |
|||
# my @values = split /,/, $2; |
|||
# s/^ *'// foreach @values; |
|||
# s/' *$// foreach @values; |
|||
# given ( $table_name ) { |
|||
# when ( /systempreferences/ ) { |
|||
# my $syspref = $values[0]; |
|||
# my $sth = $dbh->prepare( "SELECT COUNT(*) FROM systempreferences WHERE variable = ?" ); |
|||
# $sth->execute( $syspref ); |
|||
# if ( ( my $count = $sth->fetchrow_array ) > 0 ) { |
|||
# die "COHERENCY: Syspref $syspref already exists"; |
|||
# } |
|||
# } |
|||
# |
|||
# when ( /permissions/){ |
|||
# my $module_bit = $values[0]; |
|||
# my $code = $values[1]; |
|||
# my $sth = $dbh->prepare( "SELECT COUNT(*) FROM permissions WHERE module_bit = ? AND code = ?" ); |
|||
# $sth->execute($module_bit, $code); |
|||
# if ( ( my $count = $sth->fetchrow_array ) > 0 ) { |
|||
# die "COHERENCY: Permission $code already exists"; |
|||
# } |
|||
# } |
|||
# } |
|||
# } |
|||
# } |
|||
# return 1; |
|||
#} |
|||
|
|||
=head2 get_error |
|||
|
|||
my $errors = get_error() |
|||
This sub will return any mySQL error that occured during an update |
|||
|
|||
=cut |
|||
|
|||
sub get_error { |
|||
my @errors = $dbh->selectrow_array(qq{SHOW ERRORS}); # Get errors |
|||
my @warnings = $dbh->selectrow_array(qq{SHOW WARNINGS}); # Get warnings |
|||
if ( @errors ) { # Catch specifics errors |
|||
return qq{$errors[0] : $errors[1] => $errors[2]}; |
|||
} elsif ( @warnings ) { |
|||
return qq{$warnings[0] : $warnings[1] => $warnings[2]} |
|||
if $warnings[0] ne 'Note'; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
=head2 get_queries |
|||
|
|||
my $result = get_queries($filepath); |
|||
this sub will return a hashref with 2 entries: |
|||
$result->{queries} is an array with all queries to execute |
|||
$result->{comments} is an array with all comments in the .sql file |
|||
|
|||
=cut |
|||
|
|||
sub get_queries { |
|||
my ( $filepath ) = @_; |
|||
open my $fh, "<", $filepath; |
|||
my @queries; |
|||
my @comments; |
|||
if ( $filepath =~ /\.pl$/ ) { |
|||
if ( do $filepath ) { |
|||
my $infos = _get_queries(); |
|||
@queries = @{ $infos->{queries} } if exists $infos->{queries}; |
|||
@comments = @{ $infos->{comments} } if exists $infos->{comments}; |
|||
} |
|||
if ( $@ ) { |
|||
die "I can't load $filepath. Please check the execute flag and if this file is a valid perl script ($@)"; |
|||
} |
|||
} else { |
|||
my $old_delimiter = $/; |
|||
while ( <$fh> ) { |
|||
my $line = $_; |
|||
chomp $line; |
|||
$line =~ s/^\s*//; |
|||
if ( $line =~ /^--/ ) { |
|||
my @l = split $old_delimiter, $line; |
|||
if ( @l > 1 ) { |
|||
my $tmp_query; |
|||
for my $l ( @l ) { |
|||
if ( $l =~ /^--/ ) { |
|||
$l =~ s/^--\s*//; |
|||
push @comments, $l; |
|||
next; |
|||
} |
|||
$tmp_query .= $l . $old_delimiter; |
|||
} |
|||
push @queries, $tmp_query if $tmp_query; |
|||
next; |
|||
} |
|||
|
|||
$line =~ s/^--\s*//; |
|||
push @comments, $line; |
|||
next; |
|||
} |
|||
if ( $line =~ /^delimiter (.*)$/i ) { |
|||
$/ = $1; |
|||
next; |
|||
} |
|||
$line =~ s#$/##; |
|||
push @queries, $line if not $line =~ /^\s*$/; # Push if query is not empty |
|||
} |
|||
$/ = $old_delimiter; |
|||
close $fh; |
|||
} |
|||
|
|||
return { queries => \@queries, comments => \@comments }; |
|||
} |
|||
|
|||
=head2 md5_already_exists |
|||
|
|||
my $result = md5_already_exists($md5); |
|||
check if the md5 of an update has already been applied on the database. |
|||
If yes, it will return a hash with the version related to this md5 |
|||
|
|||
=cut |
|||
|
|||
sub md5_already_exists { |
|||
my ( $md5 ) = @_; |
|||
my $query = qq/SELECT version, md5 FROM updatedb_report WHERE md5 = ?/; |
|||
my $sth = $dbh->prepare( $query ); |
|||
$sth->execute( $md5 ); |
|||
my @r; |
|||
while ( my ( $version, $md5 ) = $sth->fetchrow ) { |
|||
push @r, { version => $version, md5 => $md5 }; |
|||
} |
|||
$sth->finish; |
|||
return \@r; |
|||
} |
|||
|
|||
=head2 set_infos |
|||
|
|||
set_info($version,$queries, $error, $md5); |
|||
this sub will insert into the updatedb tables what has been made on the database (queries, errors, result) |
|||
|
|||
=cut |
|||
|
|||
sub set_infos { |
|||
my ( $version, $queries, $errors, $md5 ) = @_; |
|||
SetVersion($version) if not -s $errors; |
|||
for my $query ( @{ $queries->{queries} } ) { |
|||
my $sth = $dbh->prepare("INSERT INTO updatedb_query(version, query) VALUES (?, ?)"); |
|||
$sth->execute( $version, $query ); |
|||
$sth->finish; |
|||
} |
|||
for my $error ( @$errors ) { |
|||
my $sth = $dbh->prepare("INSERT INTO updatedb_error(version, error) VALUES (?, ?)"); |
|||
$sth->execute( $version, $error ); |
|||
} |
|||
my $sth = $dbh->prepare("INSERT INTO updatedb_report(version, md5, comment, status) VALUES (?, ?, ?, ?)"); |
|||
$sth->execute( |
|||
$version, |
|||
$md5, |
|||
join ('\n', @{ $queries->{comments} }), |
|||
( @$errors > 0 ) ? 0 : 1 |
|||
); |
|||
} |
|||
|
|||
=head2 mark_as_ok |
|||
|
|||
mark_as_ok($version); |
|||
this sub will force to mark as "OK" an update that has failed |
|||
once this has been made, the status will look as "forced OK", and appear in green like versions that have been applied without any problem |
|||
|
|||
=cut |
|||
|
|||
sub mark_as_ok { |
|||
my ( $version ) = @_; |
|||
my $sth = $dbh->prepare( "UPDATE updatedb_report SET status = 2 WHERE version=?" ); |
|||
my $affected = $sth->execute( $version ); |
|||
if ( $affected < 1 ) { |
|||
my $filepath = get_filepath $version; |
|||
my $queries = get_queries $filepath; |
|||
my $md5 = get_md5 $filepath; |
|||
set_infos $version, $queries, undef, $md5; |
|||
|
|||
$sth->execute( $version ); |
|||
} |
|||
$sth->finish; |
|||
} |
|||
|
|||
=head2 is_uptodate |
|||
is_uptodate(); |
|||
return 1 if the database is up to date else 0. |
|||
The database is up to date if all versions are excecuted. |
|||
|
|||
=cut |
|||
|
|||
sub is_uptodate { |
|||
my $versions_available = C4::Update::Database::list_versions_available; |
|||
my $versions = C4::Update::Database::list_versions_already_applied; |
|||
for my $v ( @$versions_available ) { |
|||
if ( not grep { $v eq $$_{version} } @$versions ) { |
|||
return 0; |
|||
} |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
=head2 TransformToNum |
|||
|
|||
Transform the Koha version from a 4 parts string |
|||
to a number, with just 1 . (ie: it's a number) |
|||
|
|||
=cut |
|||
|
|||
sub TransformToNum { |
|||
my $version = shift; |
|||
|
|||
# remove the 3 last . to have a Perl number |
|||
$version =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/; |
|||
$version =~ s/Bug(\d+)/$1/; |
|||
return $version; |
|||
} |
|||
|
|||
sub SetVersion { |
|||
my $new_version = TransformToNum(shift); |
|||
return unless $new_version =~ /\d\.\d+/; |
|||
my $current_version = TransformToNum( C4::Context->preference('Version') ); |
|||
unless ( C4::Context->preference('Version') ) { |
|||
my $finish = $dbh->prepare(qq{ |
|||
INSERT IGNORE 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($new_version); |
|||
return; |
|||
} |
|||
if ( $new_version > $current_version ) { |
|||
my $finish = $dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='Version'"); |
|||
$finish->execute($new_version); |
|||
} |
|||
} |
|||
|
|||
=head2 TableExists($table) |
|||
|
|||
=cut |
|||
|
|||
sub TableExists { |
|||
my $table = shift; |
|||
eval { |
|||
local $dbh->{PrintError} = 0; |
|||
local $dbh->{RaiseError} = 0; |
|||
$dbh->do(qq{SELECT * FROM $table WHERE 1 = 0 }); |
|||
}; |
|||
return 1 unless $@; |
|||
return 0; |
|||
} |
|||
1; |
@ -1,60 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# Copyright BibLibre 2012 |
|||
# |
|||
# This file is part of Koha. |
|||
# |
|||
# Koha is free software; you can redistribute it and/or modify it under the |
|||
# terms of the GNU General Public License as published by the Free Software |
|||
# Foundation; either version 2 of the License, or (at your option) any later |
|||
# version. |
|||
# |
|||
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
|||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
|||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License along |
|||
# with Koha; if not, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
=head1 NAME |
|||
|
|||
ajax-updatedb-getinfos.pl |
|||
|
|||
=head1 DESCRIPTION |
|||
this script returns comments for a updatedatabase version |
|||
|
|||
=cut |
|||
|
|||
use Modern::Perl; |
|||
use CGI; |
|||
use JSON; |
|||
use C4::Update::Database; |
|||
use C4::Output; |
|||
|
|||
my $input = new CGI; |
|||
my $version = $input->param('version'); |
|||
|
|||
my $filepath; |
|||
my $queries; |
|||
eval { |
|||
$filepath = C4::Update::Database::get_filepath( $version ); |
|||
$queries = C4::Update::Database::get_queries( $filepath ); |
|||
}; |
|||
|
|||
my $param = {comments => "", queries => ""}; |
|||
if ( $@ ){ |
|||
$param->{errors} = $@; |
|||
} else { |
|||
if ( exists $queries->{comments} and @{ $queries->{comments} } ) { |
|||
$param->{comments} = join ( "<br/>", @{ $queries->{comments} } ); |
|||
} |
|||
|
|||
if ( exists $queries->{queries} and @{ $queries->{queries} } ) { |
|||
$param->{queries} = join ( "<br/>", @{ $queries->{queries} } ); |
|||
} |
|||
} |
|||
|
|||
my $json_text = to_json( $param, { utf8 => 1 } ); |
|||
|
|||
output_with_http_headers $input, undef, $json_text, 'json'; |
@ -1,101 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# Copyright Biblibre 2012 |
|||
# |
|||
# This file is part of Koha. |
|||
# |
|||
# Koha is free software; you can redistribute it and/or modify it under the |
|||
# terms of the GNU General Public License as published by the Free Software |
|||
# Foundation; either version 2 of the License, or (at your option) any later |
|||
# version. |
|||
# |
|||
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
|||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
|||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License along |
|||
# with Koha; if not, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
use Modern::Perl; |
|||
use CGI; |
|||
use C4::Auth; |
|||
use C4::Output; |
|||
use C4::Update::Database; |
|||
|
|||
my $query = new CGI; |
|||
my $op = $query->param('op') || 'list'; |
|||
|
|||
my ( $template, $borrowernumber, $cookie ) = get_template_and_user( |
|||
{ template_name => "admin/updatedatabase.tmpl", |
|||
query => $query, |
|||
type => "intranet", |
|||
authnotrequired => 0, |
|||
flagsrequired => { parameters => 1 }, |
|||
} |
|||
); |
|||
|
|||
if ( $op eq 'update' ) { |
|||
my @versions = $query->param('version'); |
|||
@versions = sort { |
|||
C4::Update::Database::TransformToNum( $a ) <=> C4::Update::Database::TransformToNum( $b ) |
|||
} @versions; |
|||
|
|||
my @reports; |
|||
for my $version ( @versions ) { |
|||
push @reports, C4::Update::Database::execute_version $version; |
|||
} |
|||
|
|||
my @report_loop = map { |
|||
my ( $v, $r ) = each %$_; |
|||
my @errors = ref ( $r ) eq 'ARRAY' |
|||
? |
|||
map { |
|||
{ error => $_ } |
|||
} @$r |
|||
: |
|||
{ error => $r }; |
|||
{ |
|||
version => $v, |
|||
report => \@errors, |
|||
} |
|||
} @reports; |
|||
$template->param( report_loop => \@report_loop ); |
|||
|
|||
$op = 'list'; |
|||
} |
|||
|
|||
if ( $op eq 'mark_as_ok' ) { |
|||
my @versions = $query->param('version'); |
|||
C4::Update::Database::mark_as_ok $_ for @versions; |
|||
$op = 'list'; |
|||
} |
|||
|
|||
if ( $op eq 'list' ) { |
|||
my $versions_available = C4::Update::Database::list_versions_available; |
|||
my $versions = C4::Update::Database::list_versions_already_applied; |
|||
|
|||
for my $v ( @$versions_available ) { |
|||
if ( not grep { $v eq $$_{version} } @$versions ) { |
|||
push @$versions, { |
|||
version => $v, |
|||
available => 1 |
|||
}; |
|||
} |
|||
} |
|||
my @sorted = sort { |
|||
C4::Update::Database::TransformToNum( $$a{version} ) <=> C4::Update::Database::TransformToNum( $$b{version} ) |
|||
} @$versions; |
|||
|
|||
my @available = grep { defined $$_{available} and $$_{available} == 1 } @sorted; |
|||
my @v_available = map { {version => $$_{version}} } @available; |
|||
|
|||
$template->param( |
|||
dev_mode => $ENV{DEBUG}, |
|||
versions => \@sorted, |
|||
nb_available => scalar @available, |
|||
available => [ map { {version => $$_{version}} } @available ], |
|||
); |
|||
} |
|||
|
|||
output_html_with_http_headers $query, $cookie, $template->output; |
@ -1,44 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# You write good Perl, so you start with Modern::Perl, of course |
|||
use Modern::Perl; |
|||
|
|||
# then you load Packages that could be usefull |
|||
use C4::Context; |
|||
# Loading this package is usefull if you need to check if a table exist (TableExists) |
|||
use C4::Update::Database; |
|||
|
|||
# you *must* have the sub _get_queries |
|||
# it returns an array of all SQL that have to be executed |
|||
# this array will be stored "forever" in your Koha database |
|||
# thus, you will be able to know which SQL has been executed |
|||
# at the time of upgrade. Very handy, because since then |
|||
# your database configuration may have changed and you'll wonder |
|||
# what has really be executed, not what would be executed today ! |
|||
|
|||
# put in an array the SQL to execute |
|||
# put in an array the comments |
|||
sub _get_queries { |
|||
my @queries; |
|||
my @comments; |
|||
push @comments, "Add sample feature"; |
|||
unless ( C4::Update::Database::TableExists('testtable') ) { |
|||
push @queries, qq{ |
|||
CREATE TABLE `testtable` ( |
|||
`id` int(11) NOT NULL AUTO_INCREMENT, |
|||
`source` text DEFAULT NULL, |
|||
`text` mediumtext NOT NULL, |
|||
`timestamp` datetime NOT NULL, |
|||
PRIMARY KEY (`id`) |
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
|||
}; |
|||
push @comments, qq { * Added the table testtable that did not exist}; |
|||
} |
|||
push @queries, qq{INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('testsyspref1',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo')}; |
|||
push @queries, qq{INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('testsyspref2',0,'Enable or disable display of Quote of the Day on the OPAC home page',NULL,'YesNo')}; |
|||
push @comments , qq{ * Added 2 sysprefs}; |
|||
|
|||
# return queries and comments |
|||
return { queries => \@queries, comments => \@comments }; |
|||
} |
|||
1; |
@ -1,27 +0,0 @@ |
|||
-- This is an example for .sql file |
|||
-- all the comments (ie= what is after --) will be identified as comment |
|||
-- and displayed as such in Koha updatedatabase interface |
|||
-- the .sql is easy: just define a separator if you plan to have multi-line SQL |
|||
-- then, your sql |
|||
|
|||
-- basic example, without delimiter defined: |
|||
UPDATE systempreferences SET value="something" WHERE variable="TestSysprefBasic"; |
|||
INSERT INTO itemtypes (itemtype, description) VALUES ('SAMPLE','A description'); |
|||
-- End of basic sample |
|||
|
|||
|
|||
-- more complex example, with delimiter defined: |
|||
DELIMITER // |
|||
-- I've defined a delimiter |
|||
-- so I can put SQL on many lines |
|||
-- Note that in this sample, the ; at the end of each query is not required. |
|||
CREATE TABLE `testtable1` ( |
|||
`entry` varchar(255) NOT NULL default '', |
|||
`weight` bigint(20) NOT NULL default 0, |
|||
PRIMARY KEY (`entry`) |
|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
|||
// |
|||
-- or on a single line, as previously |
|||
-- without ; just for the sample |
|||
INSERT INTO `systempreferences` VALUES ('TestSyspref1','2','set the level of error info sent to the browser. 0=none, 1=some, 2=most','0|1|2','Choice') |
|||
// |
@ -1,217 +0,0 @@ |
|||
[% INCLUDE 'doc-head-open.inc' %] |
|||
<title>Koha › Administration › Update Database</title> |
|||
[% INCLUDE 'doc-head-close.inc' %] |
|||
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> |
|||
<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.dataTables.min.js"></script> |
|||
[% INCLUDE 'datatables-strings.inc' %] |
|||
<script type="text/javascript" src="[% themelang %]/js/datatables.js"></script> |
|||
|
|||
<script type="text/javascript"> |
|||
//<![CDATA[ |
|||
$(document).ready(function() { |
|||
$("#versionst").dataTable($.extend(true, {}, dataTablesDefaults, { |
|||
"aaSorting" : [[0, "desc"]], |
|||
"sPaginationType": "four_button", |
|||
})); |
|||
} ); |
|||
function see_details(a){ |
|||
var div = $(a).siblings('div'); |
|||
$(div).slideToggle("fast", function() { |
|||
var isVisible = $(div).is(":visible"); |
|||
if ( isVisible ){$(a).text("Hide details");}else{$(a).text("Show details");} |
|||
} ); |
|||
} |
|||
function get_infos(version, node){ |
|||
$.getJSON('/cgi-bin/koha/admin/ajax-updatedb-getinfos.pl', |
|||
{ version: version }, |
|||
function(param) { |
|||
if ( param['errors'] ) { |
|||
$(node).replaceWith(_("Errors occured: ") + param['errors']); |
|||
} |
|||
var s; |
|||
s = "<b>" + _("Comments:") + "</b>"; |
|||
s += '<br/>'; |
|||
if ( param['comments'] ) { |
|||
s += param['comments']; |
|||
} else { |
|||
s += _("No comments"); |
|||
} |
|||
s += '<br/><br/>'; |
|||
|
|||
s += "<b>" + _("Queries:") + "</b>"; |
|||
s += '<br/>'; |
|||
if ( param['queries'] ) { |
|||
s += param['queries']; |
|||
} else { |
|||
s += _("No queries"); |
|||
} |
|||
$(node).replaceWith(s); |
|||
} |
|||
); |
|||
} |
|||
//]]> |
|||
</script> |
|||
</head> |
|||
<body> |
|||
[% INCLUDE 'header.inc' %] |
|||
[% INCLUDE 'cat-search.inc' %] |
|||
|
|||
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › Database update</div> |
|||
|
|||
<div id="doc3" class="yui-t2"> |
|||
|
|||
<div id="bd"> |
|||
<div id="yui-main"> |
|||
<div class="yui-b"> |
|||
|
|||
<h2>Database update</h2> |
|||
[% IF report_loop %] |
|||
<div class="report" style="display:block; margin:1em;"> |
|||
Report : |
|||
<ul> |
|||
[% FOREACH report_loo IN report_loop %] |
|||
<li> |
|||
[% report_loo.version %] -- |
|||
[% FOREACH r IN report_loo.report %] |
|||
[% IF r.error.error == "ALREADY_EXISTS" %] |
|||
<span style="color:orange;"> |
|||
[% r.error.filepath %] already executed in version [% r.error.old_version %] : same md5 ([% r.error.md5 %]) |
|||
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% report_loo.version %]">Mark as OK</a>] |
|||
</span> |
|||
[% ELSIF r.error.error == "LOAD_FUNCTIONS_FAILED" %] |
|||
<span style="color:red;"> |
|||
Load functions in [% r.error.filename %] failed ([% r.error.error_str %]) |
|||
</span> |
|||
[% ELSIF r.error.error == "BAD_EXTENSION" %] |
|||
<span style="color:red;"> |
|||
This extension ([% r.error.extension %]) is not take into account (only .pl or .sql)"; |
|||
</span> |
|||
[% ELSE %] |
|||
[% IF r.error == "OK" %] |
|||
<span style="color:green;"> |
|||
[% r.error %]; |
|||
</span> |
|||
[% ELSE %] |
|||
<span style="color:red;"> |
|||
[% r.error %]; |
|||
</span> |
|||
[% END %] |
|||
[% END %] |
|||
[% END %] |
|||
</li> |
|||
[% END %] |
|||
</ul> |
|||
</div> |
|||
[% END %] |
|||
<span class="infos" style="display:block; margin:1em;"> |
|||
[% IF nb_available %] |
|||
Your datebase is not up to date.<br/> |
|||
[% IF nb_available == 1 %] |
|||
1 update available [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% available.first.version %]">UPDATE [% available.first.version %]</a>] |
|||
[% ELSE %] |
|||
[% nb_available %] updates available [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update[% FOREACH av IN available %]&version=[% av.version %][% END %]">UPDATE ALL</a>]: |
|||
[% IF ( dev_mode ) %] |
|||
<ul> |
|||
[% FOREACH av IN available %] |
|||
<li>[% av.version %] [<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% av.version %]">UPDATE</a>]</li> |
|||
[% END %] |
|||
</ul> |
|||
[% END %] |
|||
[% END %] |
|||
[% ELSE %] |
|||
Your database is up to date |
|||
[% END %] |
|||
</span> |
|||
|
|||
<table id="versionst"> |
|||
<thead> |
|||
<tr> |
|||
<th>DB revision</th> |
|||
<th>Status</th> |
|||
<th>Comments</th> |
|||
<th>Details</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
[% FOREACH v IN versions %] |
|||
<tr> |
|||
<td>[% v.version %]</td> |
|||
<td> |
|||
[% IF v.available %] |
|||
Not applied |
|||
[% IF (dev_mode) %] |
|||
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=update&version=[% v.version %]">Execute</a>] |
|||
[% END %] |
|||
[% ELSE %] |
|||
[% SWITCH v.status %] |
|||
[% CASE 0 %] |
|||
<span style="color:red;"> |
|||
Applied and failed |
|||
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% v.version %]">Mark as OK</a>] |
|||
</span> |
|||
[% CASE 1 %] |
|||
<span style="color:green;">Applied and OK</span> |
|||
[% CASE 2 %] |
|||
<span style="color:green;">Applied and Forced</span> |
|||
[% CASE %] |
|||
<span style="color:red;">Status does not exist !</span> |
|||
[% END %] |
|||
[% END %] |
|||
</td> |
|||
<td> |
|||
[% FOREACH c IN v.comments %] |
|||
[% c.comment %]<br/> |
|||
[% END %] |
|||
</td> |
|||
<td width="50%"> |
|||
[% IF v.available %] |
|||
<span style="display:block;"><a href="#" onclick="get_infos('[% v.version %]', this); return false;">Get comments</a></span> |
|||
[% ELSE %] |
|||
<div class="details" style="display:none;"> |
|||
<div class="queries" style="display:block;"> |
|||
<b>Queries</b> : |
|||
<ul> |
|||
[% FOREACH q IN v.queries %] |
|||
<li>[% q.query %]<br/></li> |
|||
[% END %] |
|||
</ul> |
|||
</div> |
|||
[% IF v.status == 1 %] |
|||
<div class="status" style="display:block;"> |
|||
<b>Status</b> : |
|||
<span style="color:green;">OK</span> |
|||
</div> |
|||
[% ELSE %] |
|||
<div class="status" style="display:block;"> |
|||
<b>Status</b> : |
|||
[% IF v.status == 2 %] |
|||
<span style="color:green;">OK</span> |
|||
[FORCED] |
|||
[% ELSE %] |
|||
<span style="color:red;">Failed</span> |
|||
[<a href="/cgi-bin/koha/admin/updatedatabase.pl?op=mark_as_ok&version=[% v.version %]">Mark as OK</a>] |
|||
[% END %] |
|||
</div> |
|||
<div class="errors" style="display:block;"> |
|||
<b>Errors</b> : |
|||
<ul> |
|||
[% FOREACH e IN v.errors %] |
|||
<li><span>[% e.error %]</span></li> |
|||
[% END %] |
|||
</ul> |
|||
</div> |
|||
[% END %] |
|||
</div> |
|||
<a href="#" onclick="see_details(this);return false;">Show details</a> |
|||
[% END %] |
|||
</td> |
|||
</tr> |
|||
[% END %] |
|||
</tbody> |
|||
</table> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
@ -1,115 +0,0 @@ |
|||
#!/usr/bin/perl |
|||
|
|||
# Copyright Biblibre 2012 |
|||
# |
|||
# This file is part of Koha. |
|||
# |
|||
# Koha is free software; you can redistribute it and/or modify it under the |
|||
# terms of the GNU General Public License as published by the Free Software |
|||
# Foundation; either version 2 of the License, or (at your option) any later |
|||
# version. |
|||
# |
|||
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
|||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
|||
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License along |
|||
# with Koha; if not, write to the Free Software Foundation, Inc., |
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
use Modern::Perl; |
|||
|
|||
use C4::Context; |
|||