From c9cb55ef4710bfee111e6e2721f3ca2bf58d98f7 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Thu, 14 Jun 2012 11:46:57 +0200 Subject: [PATCH] Bug 7167: New version for updatedatabase This patch use DataTable, see BUG|BZ 6836 - css/datatables.css - lib/jquery/plugins/jquery.dataTables.min.js - js/datatables.js http://bugs.koha-community.org/show_bug.cgi?id=7167 Bug 7167 follow-up Major changes: * creating database tables for update on the fly, the 1st time the update script is called * version is checked on mainpage.pl (and here only). If syspref Version differ from kohaversion.pl, the old updatedatabase is launched. If there are updates missing from new mechanism, the updatedatabase page is reached * kohaversion check on each page is now useless in Auth.pm, removed dead code * Updated installer: at the end of the process, retrieve all updates and automatically mark them "OK", as they're included in installer Minor changes: * adding copyright * adding poddoc * updating a warning, for better clarity * switching from $$var to $var-> * small TT glitch fixed in updatedatabase.tt * about.pl now returns the Version systempreference PLUS all the patches that have been applied Bug 7167 follow-up perlcritic & numbers display & partial apply depending on DEBUG * add use strict to updatedatabase, that is now perlcritic compliant * partial apply of DB revs is now managed by DEBUG env variable = if DEBUG=0, the user can just apply every DBrev. If DEBUG=1, we're in a dev env, the user know has the option to apply DBrevs one by one Display: * in updatedatabase, small spelling changes * in about.pl, remove 0 just after . (3.06.01 is displayed as 3.6.1) * improve the display of applied numbers on about.pl - before this patch, if you have N, N+1, N+2, N+3 and N+10 DB rev applied, about was displaying : , N+1 / N+2 / N+3 / N+10 - after this patch you have N......N+3 / N+10 * add ORDER BY into list_versions_already_knows to have number retrieved in the same order whatever the order they are applied http://bugs.koha-community.org/show_bug.cgi?id=6679 Signed-off-by: Chris Nighswonger Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Improve the update.pl script * Added CLI options to update.pl * Call update.pl from the installer. Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Now, we check versions on mainpage.pl and after login Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Reimplementing Marcel's suggestions & fixes * Fixing the bugguy old version check (that was made against 3.0900000 instead of 3.0900027 -the last current kohaversion number * in the CLI script, if there is nothing to report, just say it Signed-off-by: Paul Poulain Bug 7167: Remove check_coherency As suggested by Katrin, we've removed the call to check_coherency. It intended to provide readable comments when some SQL was wrong. Removing this sub result in the SQL error being displayed. That's OK because the sysadmin or the developer can google the error, understand it, then fix it. Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Changing in .sql parsing We first split on delimiter and then extract comments. You can now put \n for delimiter comments. ex: DELIMITER ; -- this is a comment SELECT * FROM my_table; -- another comment Before this patch, we had to write: DELIMITER ; -- this is a comment; SELECT * FROM my_table; -- another comment; Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Add .pl and .sql examples Those files are in version directory, so will never be executed by the updater If you want to provide an update, do it in a 3.09/ directory (if your update is expected for 3.10 version) Note that the updater use a md5sum checker. So, if the same update is in 2 different places, it will be detected. That will be handy for changes made on both stable and master: a library running stable will get the update when updating. When upgrading to the next major release, Koha will detect the patch has already been applied, and no error will be thrown. With the previous mechanism, a DBRev ported to stable was re-executed when upgrading to master, resulting in a nasty (but usually harmless) error message Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Improve display + factorize get_queries Despite it's size, this patch is dealing with display questions only: * The text "comments" and "queries" was hardcoded in ajax-updatedb-getinfo.pl script. It has been replaced by a JSON call, returning 2 separate values, "comments:" and "queries:" is now in the template, making it translatable * Some minor tweak in the display (like putting things in bold, displaying OK in green, warnings in yellow and KO in red) * Reordering the column headers for more readability: * Status column is merged with availability, column is after status * Status/availability terms more clear: "Not applied" instead of "unknown", "Applied and OK", "Applied and failed", "Applied and forced" are the 3 other statuses * Removed one click to display comments on DBREv not yet applied: before the patch, one had to click "Show details", then "Get comments", now, "Get comments" is enough Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: FIX typos & moving a script to a proper place * renamed availables to available * renamed already_knows to already_applied * fixed FSF & copyright headers * removing a "use strict" because we already had use Modern::Perl * fixed a tiny typo in about.tt * moving update.pl to misc/bin because it's a CLI script Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: Add dependency File::Find::Rule Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167: We want to execute non-numeric version with the -all option Dealing with Marcel comment 100: > Note that the current code around line 52/53 does not > handle that correctly: > Argument "\x{74}\x{65}..." isn't numeric in numeric ge (>=) at > installer/data/mysql/update.pl line 52. Now, a non-numeric DBRev will be applied if you provide the --all parameter, without throwing the error Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167 reindentation & removing dead code * The if (! defined $ENV{PERL5LIB}... block was wrongly intented * The 3 lines running update.pl are useless: the update (new mechanism) is run from admin/updatedatabase.pl script. This part of install.pl is run only when you have "old style" DB revisions. Summary: * old mechanism = it's run as previously, by reaching the installer/install.pl?step=3 page, that applies all revisions * new mechanism = when you log-in or reach mainpage.pl, you reach admin/updatedatabase.pl, where you can see what will be run, and run it Tiny side effect = the check for old mechanism is now done *after* authentification (thus it's not done on each page call). It means that the user will have to enter login/password twice : * first to log-in to Koha * second to run installer/updatedatabase.pl?step=3 As the old mechanism is deprecated, we can expect this will happend only a few time in the history of a setup, it's not a big deal. Signed-off-by: Chris Nighswonger Bug 7167: Don't raise an error in routine TableExists Signed-off-by: Chris Nighswonger Bug 7167: FIX merge Signed-off-by: Chris Nighswonger Bug 7167: Add .pl and .sql examples Those files are in version directory, so will never be executed by the updater If you want to provide an update, do it in a 3.09/ directory (if your update is expected for 3.10 version) Note that the updater use a md5sum checker. So, if the same update is in 2 different places, it will be detected. That will be handy for changes made on both stable and master: a library running stable will get the update when updating. When upgrading to the next major release, Koha will detect the patch has already been applied, and no error will be thrown. With the previous mechanism, a DBRev ported to stable was re-executed when upgrading to master, resulting in a nasty (but usually harmless) error message Signed-off-by: Paul Poulain Signed-off-by: Chris Nighswonger Bug 7167 follow-up fix POD syntax to please koha-qa.pl Signed-off-by: Jared Camins-Esakov --- C4/Auth.pm | 125 ++-- C4/Installer.pm | 11 +- C4/Installer/PerlDependencies.pm | 7 +- C4/Update/Database.pm | 554 ++++++++++++++++++ about.pl | 42 +- admin/ajax-updatedb-getinfos.pl | 60 ++ admin/updatedatabase.pl | 101 ++++ installer/data/mysql/kohastructure.sql | 21 + .../mysql/versions/update_sample.pl.sample | 44 ++ .../mysql/versions/update_sample.sql.sample | 27 + installer/install.pl | 53 +- .../prog/en/css/staff-global.css | 8 + .../intranet-tmpl/prog/en/modules/about.tt | 2 +- .../prog/en/modules/admin/admin-home.tt | 7 + .../prog/en/modules/admin/updatedatabase.tt | 217 +++++++ mainpage.pl | 2 + misc/bin/updatedb.pl | 115 ++++ 17 files changed, 1297 insertions(+), 99 deletions(-) create mode 100644 C4/Update/Database.pm create mode 100755 admin/ajax-updatedb-getinfos.pl create mode 100755 admin/updatedatabase.pl create mode 100644 installer/data/mysql/versions/update_sample.pl.sample create mode 100644 installer/data/mysql/versions/update_sample.sql.sample create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/updatedatabase.tt create mode 100755 misc/bin/updatedb.pl diff --git a/C4/Auth.pm b/C4/Auth.pm index b32136a033..b04df8b041 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -28,6 +28,7 @@ require Exporter; use C4::Context; use C4::Templates; # to get the template use C4::Branch; # GetBranches +use C4::Update::Database; use C4::VirtualShelves; use POSIX qw/strftime/; use List::MoreUtils qw/ any /; @@ -134,9 +135,9 @@ sub get_template_and_user { my $in = shift; my $template = C4::Templates::gettemplate( $in->{'template_name'}, $in->{'type'}, $in->{'query'} ); - my ( $user, $cookie, $sessionID, $flags ); + my ( $user, $cookie, $sessionID, $flags, $new_session ); if ( $in->{'template_name'} !~m/maintenance/ ) { - ( $user, $cookie, $sessionID, $flags ) = checkauth( + ( $user, $cookie, $sessionID, $flags, $new_session ) = checkauth( $in->{'query'}, $in->{'authnotrequired'}, $in->{'flagsrequired'}, @@ -468,6 +469,12 @@ sub get_template_and_user { $template->param(OpacPublic => '1') if ($user || C4::Context->preference("OpacPublic")); } + + if ( $new_session ) { + # Check the version and redirect if DB is not up-to-date + version_check($in->{query}, $in->{'type'}, $cookie); + } + return ( $template, $borrowernumber, $cookie, $flags); } @@ -549,50 +556,6 @@ has authenticated. =cut -sub _version_check { - my $type = shift; - my $query = shift; - my $version; - # If Version syspref is unavailable, it means Koha is beeing installed, - # and so we must redirect to OPAC maintenance page or to the WebInstaller - # also, if OpacMaintenance is ON, OPAC should redirect to maintenance - if (C4::Context->preference('OpacMaintenance') && $type eq 'opac') { - warn "OPAC Install required, redirecting to maintenance"; - print $query->redirect("/cgi-bin/koha/maintenance.pl"); - safe_exit; - } - unless ( $version = C4::Context->preference('Version') ) { # assignment, not comparison - if ( $type ne 'opac' ) { - warn "Install required, redirecting to Installer"; - print $query->redirect("/cgi-bin/koha/installer/install.pl"); - } else { - warn "OPAC Install required, redirecting to maintenance"; - print $query->redirect("/cgi-bin/koha/maintenance.pl"); - } - safe_exit; - } - - # check that database and koha version are the same - # there is no DB version, it's a fresh install, - # go to web installer - # there is a DB version, compare it to the code version - my $kohaversion=C4::Context::KOHAVERSION; - # remove the 3 last . to have a Perl number - $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/; - $debug and print STDERR "kohaversion : $kohaversion\n"; - if ($version < $kohaversion){ - my $warning = "Database update needed, redirecting to %s. Database is $version and Koha is $kohaversion"; - if ($type ne 'opac'){ - warn sprintf($warning, 'Installer'); - print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3"); - } else { - warn sprintf("OPAC: " . $warning, 'maintenance'); - print $query->redirect("/cgi-bin/koha/maintenance.pl"); - } - safe_exit; - } -} - sub _session_log { (@_) or return 0; open my $fh, '>>', "/tmp/sessionlog" or warn "ERROR: Cannot append to /tmp/sessionlog"; @@ -609,6 +572,38 @@ sub _timeout_syspref { return $timeout; } +sub version_check { + my ( $query, $type, $cookie ) = @_; + # check we have a Version. Otherwise => go to installer + unless ( C4::Context->preference('Version') ) { + if ( $type ne 'opac' ) { + $debug && warn "Install required, redirecting to Installer"; + print $query->redirect("/cgi-bin/koha/installer/install.pl"); + } else { + $debug && warn "OPAC Install required, redirecting to maintenance"; + print $query->redirect("/cgi-bin/koha/maintenance.pl"); + } + safe_exit; + } + + # check if you're uptodate, and if you're not, head to updater + my $koha39 = "3.0900028"; + + # Old updatedatabase method + if (C4::Context->preference('Version') < $koha39) { + print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3"); + safe_exit; + } + + # New updatedatabase method + unless ( C4::Update::Database::is_uptodate() ) { + # not up-to-date, redirect to updatedatabase page + warn "redirect to updatedatabase"; + print $query->redirect(-location => "/cgi-bin/koha/admin/updatedatabase.pl", -cookie => $cookie); + safe_exit; + } +} + sub checkauth { my $query = shift; $debug and warn "Checking Auth"; @@ -617,11 +612,16 @@ sub checkauth { my $flagsrequired = shift; my $type = shift; $type = 'opac' unless $type; + my $new_session = 0; my $dbh = C4::Context->dbh; my $timeout = _timeout_syspref(); + # days + if ($timeout =~ /(\d+)[dD]/) { + $timeout = $1 * 86400; + }; + $timeout = 600 unless $timeout; - _version_check($type,$query); # state variables my $loggedin = 0; my %info; @@ -725,6 +725,7 @@ sub checkauth { my $sessionID = $session->id; C4::Context->_new_userenv($sessionID); $cookie = $query->cookie( CGISESSID => $sessionID ); + $userid = $query->param('userid'); if ( ( $cas && $query->param('ticket') ) || $userid @@ -739,6 +740,7 @@ sub checkauth { checkpw( $dbh, $userid, $password, $query ); $userid = $retuserid; $info{'invalidCasLogin'} = 1 unless ($return); + $new_session = 1; } elsif ( ( $pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'} ) @@ -777,6 +779,7 @@ sub checkauth { ( $return, $cardnumber, $retuserid ) = checkpw( $dbh, $userid, $password, $query ); $userid = $retuserid if ( $retuserid ne '' ); + $new_session = 1; } if ($return) { #_session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime)); @@ -918,7 +921,7 @@ sub checkauth { unless ($cookie) { $cookie = $query->cookie( CGISESSID => '' ); } - return ( $userid, $cookie, $sessionID, $flags ); + return ( $userid, $cookie, $sessionID, $flags, $new_session ); } # @@ -1063,19 +1066,6 @@ sub check_api_auth { my $dbh = C4::Context->dbh; my $timeout = _timeout_syspref(); - unless (C4::Context->preference('Version')) { - # database has not been installed yet - return ("maintenance", undef, undef); - } - my $kohaversion=C4::Context::KOHAVERSION; - $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/; - if (C4::Context->preference('Version') < $kohaversion) { - # database in need of version update; assume that - # no API should be called while databsae is in - # this condition. - return ("maintenance", undef, undef); - } - # FIXME -- most of what follows is a copy-and-paste # of code from checkauth. There is an obvious need # for refactoring to separate the various parts of @@ -1295,19 +1285,6 @@ sub check_cookie_auth { my $dbh = C4::Context->dbh; my $timeout = _timeout_syspref(); - unless (C4::Context->preference('Version')) { - # database has not been installed yet - return ("maintenance", undef); - } - my $kohaversion=C4::Context::KOHAVERSION; - $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/; - if (C4::Context->preference('Version') < $kohaversion) { - # database in need of version update; assume that - # no API should be called while databsae is in - # this condition. - return ("maintenance", undef); - } - # FIXME -- most of what follows is a copy-and-paste # of code from checkauth. There is an obvious need # for refactoring to separate the various parts of diff --git a/C4/Installer.pm b/C4/Installer.pm index 304698ed0e..759a6be5df 100644 --- a/C4/Installer.pm +++ b/C4/Installer.pm @@ -23,6 +23,7 @@ use strict; our $VERSION = 3.07.00.049; use C4::Context; use C4::Installer::PerlModules; +use C4::Update::Database; =head1 NAME @@ -466,7 +467,15 @@ Koha software version. sub set_version_syspref { my $self = shift; - + # get all updatedatabase, and mark them as passed, as it's a fresh install + my $versions = C4::Update::Database::list_versions_available(); + for my $v ( @$versions ) { + my $queries; + $queries->{queries} = ["initial setup"]; + $queries->{comments} = ["initial setup"]; + C4::Update::Database::set_infos($v,$queries,undef,undef); + } + # mark the "old" 3.6 version number my $kohaversion=C4::Context::KOHAVERSION; # remove the 3 last . to have a Perl number $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/; diff --git a/C4/Installer/PerlDependencies.pm b/C4/Installer/PerlDependencies.pm index 41fa8db48c..daf246e6e2 100644 --- a/C4/Installer/PerlDependencies.pm +++ b/C4/Installer/PerlDependencies.pm @@ -628,12 +628,17 @@ our $PERL_DEPS = { 'usage' => 'Core', 'required' => '0', 'min_ver' => '1.09', - }, + }, 'String::Random' => { 'usage' => 'OpacSelfRegistration', 'required' => '0', 'min_ver' => '0.22', }, + 'File::Find::Rule' => { + 'usage' => 'Core', + 'required' => '1', + 'min_ver' => '0.33', + }, }; 1; diff --git a/C4/Update/Database.pm b/C4/Update/Database.pm new file mode 100644 index 0000000000..5a0d392393 --- /dev/null +++ b/C4/Update/Database.pm @@ -0,0 +1,554 @@ +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; diff --git a/about.pl b/about.pl index 3c641b3808..f00129b363 100755 --- a/about.pl +++ b/about.pl @@ -32,6 +32,7 @@ use C4::Output; use C4::Auth; use C4::Context; use C4::Installer; +use C4::Update::Database; #use Smart::Comments '####'; @@ -47,7 +48,45 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( } ); -my $kohaVersion = C4::Context::KOHAVERSION; +my $kohaVersion = C4::Context->preference("Version"); +# restore ., for display consistency +$kohaVersion =~ /(.)\.(..)(..)(...)/; +# transform digits to Perl number, to display 3.6.1.2 instead of 3.06.01.002 +$kohaVersion = ($1+0).".".($2+0).".".($3+0).".".($4+0); + +my $dbrev_applied=""; # the list of database revisions + +# the $kohaVersion is duplicated since 3.7: the 3.6 (that uses the old mechanism) and the 3.7 (new mechanism). +# Both versions reflects how the database has been upgraded +my $already_applied = C4::Update::Database::list_versions_already_applied(); +# $last_known contains the previous DBrev applied number (all . removed). It's used to have a . instead of a number in case of continuous updates +my $last_known=0; +# $last_known_sep contains the previous DBrev applied with the separator (used for display) +my $last_known_sep=""; +for my $v ( @$already_applied ) { + my $current = $v->{version}; + $current =~s/\.//g; + # if the current number is the previous one +1, then just add a ., for a better display N.........N+10, for example + # (instead of N / N+1 / N+2 / ...) + if ($current==$last_known+1) { + $dbrev_applied.="."; + } else { # we're not N+1, start a new range + # if version don't end by a ., no need to add the current loop number + # this avoid having N...N (in case of an isolated BDrev number) + if ($last_known & $dbrev_applied =~ /\.$/) { + $dbrev_applied .= "...".$last_known_sep; + } + # start a new range + $dbrev_applied .= " ".$v->{version}; + } + $last_known= $current; + $last_known_sep=$v->{version}; +} +# add the last DB rev number, we don't want to end with "..." +if ($dbrev_applied =~ /\.$/) { + $dbrev_applied .= "...".$last_known_sep; +} + my $osVersion = `uname -a`; my $perl_path = $^X; if ($^O ne 'VMS') { @@ -76,6 +115,7 @@ my $warnIsRootUser = (! $loggedinuser); $template->param( kohaVersion => $kohaVersion, + dbrev_applied => $dbrev_applied, osVersion => $osVersion, perlPath => $perl_path, perlVersion => $perlVersion, diff --git a/admin/ajax-updatedb-getinfos.pl b/admin/ajax-updatedb-getinfos.pl new file mode 100755 index 0000000000..0aa65f0a41 --- /dev/null +++ b/admin/ajax-updatedb-getinfos.pl @@ -0,0 +1,60 @@ +#!/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 ( "
", @{ $queries->{comments} } ); + } + + if ( exists $queries->{queries} and @{ $queries->{queries} } ) { + $param->{queries} = join ( "
", @{ $queries->{queries} } ); + } +} + +my $json_text = to_json( $param, { utf8 => 1 } ); + +output_with_http_headers $input, undef, $json_text, 'json'; diff --git a/admin/updatedatabase.pl b/admin/updatedatabase.pl new file mode 100755 index 0000000000..013414d624 --- /dev/null +++ b/admin/updatedatabase.pl @@ -0,0 +1,101 @@ +#!/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; diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index ed673da455..68ce9d01c9 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -2083,6 +2083,27 @@ CREATE TABLE `tags_index` ( -- a weighted list of all tags and where they are us REFERENCES `biblio` (`biblionumber`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Table structure for database updates +-- +CREATE TABLE`updatedb_error` ( + `version` varchar(32) DEFAULT NULL, + `error` text +) ENGINE=InnoDB CHARSET=utf8; + +CREATE TABLE `updatedb_query` ( + `version` varchar(32) DEFAULT NULL, + `query` text +) ENGINE=InnoDB CHARSET=utf8; + +CREATE TABLE `updatedb_report` ( + `version` text, + `md5` varchar(50) DEFAULT NULL, + `comment` text, + `status` int(1) DEFAULT NULL +) ENGINE=InnoDB CHARSET=utf8; + -- -- Table structure for table `userflags` -- diff --git a/installer/data/mysql/versions/update_sample.pl.sample b/installer/data/mysql/versions/update_sample.pl.sample new file mode 100644 index 0000000000..49e62b3627 --- /dev/null +++ b/installer/data/mysql/versions/update_sample.pl.sample @@ -0,0 +1,44 @@ +#!/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; diff --git a/installer/data/mysql/versions/update_sample.sql.sample b/installer/data/mysql/versions/update_sample.sql.sample new file mode 100644 index 0000000000..bb2cc8db64 --- /dev/null +++ b/installer/data/mysql/versions/update_sample.sql.sample @@ -0,0 +1,27 @@ +-- 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') +// diff --git a/installer/install.pl b/installer/install.pl index d9feac4b43..01360e636d 100755 --- a/installer/install.pl +++ b/installer/install.pl @@ -312,29 +312,24 @@ elsif ( $step && $step == 3 ) { # Not 1st install, the only sub-step : update database # #Do updatedatabase And report - - if ( ! defined $ENV{PERL5LIB} ) { - my $find = "C4/Context.pm"; - my $path = $INC{$find}; - $path =~ s/\Q$find\E//; - $ENV{PERL5LIB} = "$path:$path/installer"; - warn "# plack? inserted PERL5LIB $ENV{PERL5LIB}\n"; - } - - my $cmd = C4::Context->config("intranetdir") . "/installer/data/$info{dbms}/updatedatabase.pl"; - my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = IPC::Cmd::run(command => $cmd, verbose => 0); - - if (@$stdout_buf) { - $template->param(update_report => [ map { { line => $_ } } split(/\n/, join('', @$stdout_buf)) ] ); - $template->param(has_update_succeeds => 1); - } - if (@$stderr_buf) { - $template->param(update_errors => [ map { { line => $_ } } split(/\n/, join('', @$stderr_buf)) ] ); - $template->param(has_update_errors => 1); - warn "The following errors were returned while attempting to run the updatedatabase.pl script:\n"; - foreach my $line (@$stderr_buf) {warn "$line\n";} + if ( ! defined $ENV{PERL5LIB} ) { + my $find = "C4/Context.pm"; + my $path = $INC{$find}; + $path =~ s/\Q$find\E//; + $ENV{PERL5LIB} = "$path:$path/installer"; + warn "# plack? inserted PERL5LIB $ENV{PERL5LIB}\n"; } + my $koha39 = "3.0900028"; + my $cmd; + # Old updatedatabase method + my $current_version = C4::Context->preference('Version'); + if ( $current_version < $koha39 ) { + $cmd = C4::Context->config("intranetdir") . "/installer/data/$info{dbms}/updatedatabase.pl"; + my ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf) = IPC::Cmd::run(command => $cmd, verbose => 0); + print_std( "updatedatabase.pl", $stdout_buf, $stderr_buf ); + $current_version= $koha39; + } $template->param( $op => 1 ); } else { @@ -406,4 +401,20 @@ else { } } } + +sub print_std { + my ( $script, $stdout_buf, $stderr_buf ) = @_; + if (@$stdout_buf) { + $template->param(update_report => [ map { { line => $_ } } split(/\n/, join('', @$stdout_buf)) ] ); + $template->param(has_update_succeeds => 1); + } + if (@$stderr_buf) { + $template->param(update_errors => [ map { { line => $_ } } split(/\n/, join('', @$stderr_buf)) ] ); + $template->param(has_update_errors => 1); + warn "The following errors were returned while attempting to run the $script script:\n"; + foreach my $line (@$stderr_buf) {warn "$line\n";} + } +} + + output_html_with_http_headers $query, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css index 349a65db54..84079750c3 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -2042,6 +2042,14 @@ div.pager p { margin: 0; } +tr.dragClass td { + background-color: grey; + color: yellow; +} +.underline { + text-decoration : underline; +} + div#acqui_order_supplierlist > div.supplier { border: 1px solid #EEEEEE; margin: 0.5em; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/about.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/about.tt index 6c8ea00dba..7858e0992c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/about.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/about.tt @@ -37,7 +37,7 @@ - + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt index cbf3b92fb2..b2a3b6983b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt @@ -110,6 +110,13 @@
Did you mean?
Choose which plugins to use to suggest searches to patrons and staff.
+ +

Update Database

+
+
Check your updates
+
Verify your database versions and execute new updates
+
+ diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/updatedatabase.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/updatedatabase.tt new file mode 100644 index 0000000000..e0f9ceb54d --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/updatedatabase.tt @@ -0,0 +1,217 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Administration › Update Database +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'datatables-strings.inc' %] + + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'cat-search.inc' %] + + + +
+ +
+
+
+ +

Database update

+ [% IF report_loop %] +
+ Report : +
    + [% FOREACH report_loo IN report_loop %] +
  • + [% report_loo.version %] -- + [% FOREACH r IN report_loo.report %] + [% IF r.error.error == "ALREADY_EXISTS" %] + + [% r.error.filepath %] already executed in version [% r.error.old_version %] : same md5 ([% r.error.md5 %]) + [Mark as OK] + + [% ELSIF r.error.error == "LOAD_FUNCTIONS_FAILED" %] + + Load functions in [% r.error.filename %] failed ([% r.error.error_str %]) + + [% ELSIF r.error.error == "BAD_EXTENSION" %] + + This extension ([% r.error.extension %]) is not take into account (only .pl or .sql)"; + + [% ELSE %] + [% IF r.error == "OK" %] + + [% r.error %]; + + [% ELSE %] + + [% r.error %]; + + [% END %] + [% END %] + [% END %] +
  • + [% END %] +
+
+ [% END %] + + [% IF nb_available %] + Your datebase is not up to date.
+ [% IF nb_available == 1 %] + 1 update available [UPDATE [% available.first.version %]] + [% ELSE %] + [% nb_available %] updates available [UPDATE ALL]: + [% IF ( dev_mode ) %] +
    + [% FOREACH av IN available %] +
  • [% av.version %] [UPDATE]
  • + [% END %] +
+ [% END %] + [% END %] + [% ELSE %] + Your database is up to date + [% END %] +
+ +
Server information
Koha version: [% kohaVersion |html %]
Koha version: [% kohaVersion |html %] with the following database revisions applied: [% dbrev_applied|html %]
OS version ('uname -a'): [% osVersion |html %]
Perl interpreter: [% perlPath |html %]
Perl version: [% perlVersion |html %]
+ + + + + + + + + + [% FOREACH v IN versions %] + + + + + + + [% END %] + +
DB revisionStatusCommentsDetails
[% v.version %] + [% IF v.available %] + Not applied + [% IF (dev_mode) %] + [Execute] + [% END %] + [% ELSE %] + [% SWITCH v.status %] + [% CASE 0 %] + + Applied and failed + [Mark as OK] + + [% CASE 1 %] + Applied and OK + [% CASE 2 %] + Applied and Forced + [% CASE %] + Status does not exist ! + [% END %] + [% END %] + + [% FOREACH c IN v.comments %] + [% c.comment %]
+ [% END %] +
+ [% IF v.available %] + Get comments + [% ELSE %] + + Show details + [% END %] +
+ + + + + + diff --git a/mainpage.pl b/mainpage.pl index 9085630e69..8aa8495868 100755 --- a/mainpage.pl +++ b/mainpage.pl @@ -42,6 +42,8 @@ my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( } ); +C4::Auth::version_check($query, 'intranet', $cookie); + my $all_koha_news = &GetNewsToDisplay("koha"); my $koha_news_count = scalar @$all_koha_news; diff --git a/misc/bin/updatedb.pl b/misc/bin/updatedb.pl new file mode 100755 index 0000000000..8b613ecce5 --- /dev/null +++ b/misc/bin/updatedb.pl @@ -0,0 +1,115 @@ +#!/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; +use C4::Update::Database; +use Getopt::Long; + +my $help; +my $version; +my $list; +my $all; +my $min; + +GetOptions( + 'h|help|?' => \$help, + 'm:s' => \$version, + 'l|list' => \$list, + 'a|all' => \$all, + 'min:s' => \$min, +); + +if ( $help or not( $version or $list or $all ) ) { + usage(); + exit; +} + +my @reports; +if ($version) { + my $report = C4::Update::Database::execute_version($version); + push @reports, $report; +} + +if ($list) { + my $available = C4::Update::Database::list_versions_available(); + my $already_applied = C4::Update::Database::list_versions_already_applied(); + say "Versions available:"; + for my $v (@$available) { + if ( not grep { $v eq $_->{version} } @$already_applied ) { + say "\t- $_" for $v; + } + } + say "Versions already applied:"; + say "\t- $_->{version}" for @$already_applied; + +} + +if ($all) { + my $versions_available = C4::Update::Database::list_versions_available(); + my $versions = C4::Update::Database::list_versions_already_applied; + my $min_version = + $min + ? $min =~ m/\d\.\d{2}\.\d{2}\.\d{3}/ + ? C4::Update::Database::TransformToNum($min) + : $min + : 0; + + for my $v (@$versions_available) { + # We execute ALL versions where version number >= min_version + # OR version is not a number + if ( not grep { $v eq $_->{version} } @$versions + and ( not $v =~ /\d\.\d{2}\.\d{2}\.\d{3}/ or + C4::Update::Database::TransformToNum($v) >= $min_version ) ) + { + my $report = C4::Update::Database::execute_version $v; + push @reports, $report; + } + } +} + +if ( $version or $all ) { + say @reports ? "Report:" : "Nothing to report"; + for my $report (@reports) { + my ( $v, $r ) = each %$report; + if ( ref($r) eq 'HASH' ) { + say "\t$v => $r->{error}"; + } + elsif ( ref($r) eq 'ARRAY' ) { + say "\t$_" for @$r; + } + else { + say "\t$v => $r"; + } + } +} + +sub usage { + say "update.pl"; + say "This script updates your database for you"; + say "Usage:"; + say "\t-h\tShow this help message"; + say "\t-m\tExecute a given version"; + say "\t-l\tList all the versions"; + say "\t-all\tExecute all available versions"; + say + "\t-min\tWith -all, Execute all available versions since a given version"; + say "\t\tCan be X.XX.XX.XXX or X.XXXXXXX"; +} -- 2.39.5