Bug 10403: (follow-up) fix test to use vendor created earlier during test
[koha.git] / C4 / Installer.pm
index caeb2ff..2add0e8 100644 (file)
@@ -13,14 +13,16 @@ package C4::Installer;
 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 #
 # 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., 59 Temple Place,
-# Suite 330, Boston, MA  02111-1307 USA
+# 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 strict;
 
 use strict;
+#use warnings; FIXME - Bug 2505
 
 
-our $VERSION = 3.00;
+our $VERSION = 3.07.00.049;
 use C4::Context;
 use C4::Context;
+use C4::Installer::PerlModules;
 
 =head1 NAME
 
 
 =head1 NAME
 
@@ -28,35 +30,25 @@ C4::Installer
 
 =head1 SYNOPSIS
 
 
 =head1 SYNOPSIS
 
-use C4::Installer;
-
-my $installer = C4::Installer->new();
-
-my $all_languages = getAllLanguages();
-
-my $error = $installer->load_db_schema();
-
-my $list = $installer->sql_file_list('en', 'marc21', { optional => 1, mandatory => 1 });
-
-my ($fwk_language, $error_list) = $installer->load_sql_in_order($all_languages, @$list);
-
-$installer->set_version_syspref();
-
-$installer->set_marcflavour_syspref('MARC21');
-
-$installer->set_indexing_engine(0);
+ use C4::Installer;
+ my $installer = C4::Installer->new();
+ my $all_languages = getAllLanguages();
+ my $error = $installer->load_db_schema();
+ my $list;
+ #fill $list with list of sql files
+ my ($fwk_language, $error_list) = $installer->load_sql_in_order($all_languages, @$list);
+ $installer->set_version_syspref();
+ $installer->set_marcflavour_syspref('MARC21');
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
+=cut
+
 =head1 METHODS
 
 =head2 new
 
 =head1 METHODS
 
 =head2 new
 
-=over 4
-
-my $installer = C4::Installer->new();
-
-=back
+  my $installer = C4::Installer->new();
 
 Creates a new installer.
 
 
 Creates a new installer.
 
@@ -74,48 +66,22 @@ sub new {
     $self->{'port'}     = C4::Context->config("port");
     $self->{'user'}     = C4::Context->config("user");
     $self->{'password'} = C4::Context->config("pass");
     $self->{'port'}     = C4::Context->config("port");
     $self->{'user'}     = C4::Context->config("user");
     $self->{'password'} = C4::Context->config("pass");
-    $self->{'dbh'} = DBI->connect("DBI:$self->{dbms}:dbname=$self->{dbname};host=$self->{hostname}" . 
+    $self->{'dbh'} = DBI->connect("DBI:$self->{dbms}:dbname=$self->{dbname};host=$self->{hostname}" .
                                   ( $self->{port} ? ";port=$self->{port}" : "" ),
                                   $self->{'user'}, $self->{'password'});
     $self->{'language'} = undef;
     $self->{'marcflavour'} = undef;
                                   ( $self->{port} ? ";port=$self->{port}" : "" ),
                                   $self->{'user'}, $self->{'password'});
     $self->{'language'} = undef;
     $self->{'marcflavour'} = undef;
+       $self->{'dbh'}->do('set NAMES "utf8"');
+    $self->{'dbh'}->{'mysql_enable_utf8'}=1;
 
     bless $self, $class;
     return $self;
 }
 
 
     bless $self, $class;
     return $self;
 }
 
-=head2 marcflavour_list
-
-=over 4
-
-my ($marcflavours) = $installer->marcflavour_list($lang);
-
-=back
-
-Return a arrayref of the MARC flavour sets available for the
-specified language C<$lang>.  Returns 'undef' if a directory
-for the language does not exist.
-
-=cut
-
-sub marcflavour_list {
-    my $self = shift;
-    my $lang = shift;
-
-    my $dir = C4::Context->config('intranetdir') . "/installer/data/$self->{dbms}/$lang/marcflavour";
-    opendir(MYDIR, $dir) or return;
-    my @list = grep { !/^\.|CVS/ && -d "$dir/$_" } readdir(MYDIR);
-    closedir MYDIR;
-    return \@list;
-}
-
 =head2 marc_framework_sql_list
 
 =head2 marc_framework_sql_list
 
-=over 4
-
-my ($defaulted_to_en, $list) = $installer->marc_framework_sql_list($lang, $marcflavour);
-
-=back
+  my ($defaulted_to_en, $list) = 
+     $installer->marc_framework_sql_list($lang, $marcflavour);
 
 Returns in C<$list> a structure listing the filename, description, section,
 and mandatory/optional status of MARC framework scripts available for C<$lang>
 
 Returns in C<$list> a structure listing the filename, description, section,
 and mandatory/optional status of MARC framework scripts available for C<$lang>
@@ -148,7 +114,7 @@ sub marc_framework_sql_list {
     }
     my @listdir = sort grep { !/^\.|marcflavour/ && -d "$dir/$_" } readdir(MYDIR);
     closedir MYDIR;
     }
     my @listdir = sort grep { !/^\.|marcflavour/ && -d "$dir/$_" } readdir(MYDIR);
     closedir MYDIR;
-   
+
     my @fwklist;
     my $request = $self->{'dbh'}->prepare("SELECT value FROM systempreferences WHERE variable='FrameworksLoaded'");
     $request->execute;
     my @fwklist;
     my $request = $self->{'dbh'}->prepare("SELECT value FROM systempreferences WHERE variable='FrameworksLoaded'");
     $request->execute;
@@ -167,8 +133,8 @@ sub marc_framework_sql_list {
         my @frameworklist;
         map {
             my $name = substr( $_, 0, -4 );
         my @frameworklist;
         map {
             my $name = substr( $_, 0, -4 );
-            open FILE, "<:utf8","$dir/$requirelevel/$name.txt";
-            my $lines = <FILE>;
+            open my $fh, "<:encoding(UTF-8)", "$dir/$requirelevel/$name.txt";
+            my $lines = <$fh>;
             $lines =~ s/\n|\r/<br \/>/g;
             use utf8;
             utf8::encode($lines) unless ( utf8::is_utf8($lines) );
             $lines =~ s/\n|\r/<br \/>/g;
             use utf8;
             utf8::encode($lines) unless ( utf8::is_utf8($lines) );
@@ -190,17 +156,13 @@ sub marc_framework_sql_list {
         $cell{"code"}       = lc($requirelevel);
         push @fwklist, \%cell;
     }
         $cell{"code"}       = lc($requirelevel);
         push @fwklist, \%cell;
     }
+
     return ($defaulted_to_en, \@fwklist);
 }
 
 =head2 sample_data_sql_list
 
     return ($defaulted_to_en, \@fwklist);
 }
 
 =head2 sample_data_sql_list
 
-=over 4
-
-my ($defaulted_to_en, $list) = $installer->sample_data_sql_list($lang);
-
-=back
+  my ($defaulted_to_en, $list) = $installer->sample_data_sql_list($lang);
 
 Returns in C<$list> a structure listing the filename, description, section,
 and mandatory/optional status of sample data scripts available for C<$lang>.
 
 Returns in C<$list> a structure listing the filename, description, section,
 and mandatory/optional status of sample data scripts available for C<$lang>.
@@ -249,8 +211,8 @@ sub sample_data_sql_list {
         my @frameworklist;
         map {
             my $name = substr( $_, 0, -4 );
         my @frameworklist;
         map {
             my $name = substr( $_, 0, -4 );
-            open FILE, "<:utf8","$dir/$requirelevel/$name.txt";
-            my $lines = <FILE>;
+            open my $fh , "<:encoding(UTF-8)", "$dir/$requirelevel/$name.txt";
+            my $lines = <$fh>;
             $lines =~ s/\n|\r/<br \/>/g;
             use utf8;
             utf8::encode($lines) unless ( utf8::is_utf8($lines) );
             $lines =~ s/\n|\r/<br \/>/g;
             use utf8;
             utf8::encode($lines) unless ( utf8::is_utf8($lines) );
@@ -275,52 +237,9 @@ sub sample_data_sql_list {
     return ($defaulted_to_en, \@levellist);
 }
 
     return ($defaulted_to_en, \@levellist);
 }
 
-=head2 sql_file_list
-
-=over 4
-
-my $list = $installer->sql_file_list($lang, $marcflavour, $subset_wanted);
+=head2 load_db_schema
 
 
-=back
-
-Returns an arrayref containing the filepaths of installer SQL scripts
-available for laod.  The C<$lang> and C<$marcflavour> arguments
-specify the desired language and MARC flavour. while C<$subset_wanted>
-is a hashref containing possible named parameters 'mandatory' and 'optional'.
-
-=cut
-
-sub sql_file_list {
-    my $self = shift;
-    my $lang = shift;
-    my $marcflavour = shift;
-    my $subset_wanted = shift;
-
-    my ($marc_defaulted_to_en, $marc_sql) = $self->marc_framework_sql_list($lang, $marcflavour);
-    my ($sample_defaulted_to_en, $sample_sql) = $self->sample_data_sql_list($lang);
-    
-    my @sql_list = ();
-    map { 
-        map {
-            if ($subset_wanted->{'mandatory'}) {
-                push @sql_list, $_->{'fwkfile'} if $_->{'mandatory'};
-            }
-            if ($subset_wanted->{'optional'}) {
-                push @sql_list, $_->{'fwkfile'} unless $_->{'mandatory'};
-            }
-        } @{ $_->{'frameworks'} }
-    } (@$marc_sql, @$sample_sql);
-    
-    return \@sql_list
-}
-
-=head2 load_db_schema 
-
-=over 4
-
-my $error = $installer->load_db_schema();
-
-=back
+  my $error = $installer->load_db_schema();
 
 Loads the SQL script that creates Koha's tables and indexes.  The
 return value is a string containing error messages reported by the
 
 Loads the SQL script that creates Koha's tables and indexes.  The
 return value is a string containing error messages reported by the
@@ -339,11 +258,7 @@ sub load_db_schema {
 
 =head2 load_sql_in_order
 
 
 =head2 load_sql_in_order
 
-=over 4
-
-my ($fwk_language, $list) = $installer->load_sql_in_order($all_languages, @sql_list);
-
-=back
+  my ($fwk_language, $list) = $installer->load_sql_in_order($all_languages, @sql_list);
 
 Given a list of SQL scripts supplied in C<@sql_list>, loads each of them
 into the database and sets the FrameworksLoaded system preference to names
 
 Given a list of SQL scripts supplied in C<@sql_list>, loads each of them
 into the database and sets the FrameworksLoaded system preference to names
@@ -354,15 +269,15 @@ directory path).  This means that dependencies among the scripts are to
 be resolved by carefully naming them, keeping in mind that the directory name
 does *not* currently count.
 
 be resolved by carefully naming them, keeping in mind that the directory name
 does *not* currently count.
 
-FIXME: this is a rather delicate way of dealing with dependencies between 
-       the install scripts.
+B<FIXME:> this is a rather delicate way of dealing with dependencies between
+the install scripts.
 
 The return value C<$list> is an arrayref containing a hashref for each
 "level" or directory containing SQL scripts; the hashref in turns contains
 a list of hashrefs containing a list of each script load and any error
 messages associated with the loading of each script.
 
 
 The return value C<$list> is an arrayref containing a hashref for each
 "level" or directory containing SQL scripts; the hashref in turns contains
 a list of hashrefs containing a list of each script load and any error
 messages associated with the loading of each script.
 
-FIXME: The C<$fwk_language> code probably doesn't belong and needs to be
+B<FIXME:> The C<$fwk_language> code probably doesn't belong and needs to be
 moved to a different method.
 
 =cut
 moved to a different method.
 
 =cut
@@ -383,6 +298,9 @@ sub load_sql_in_order {
     $request->execute;
     my ($systempreference) = $request->fetchrow;
     $systempreference = '' unless defined $systempreference; # avoid warning
     $request->execute;
     my ($systempreference) = $request->fetchrow;
     $systempreference = '' unless defined $systempreference; # avoid warning
+    # Make sure the global sysprefs.sql file is loaded first
+    my $globalsysprefs = C4::Context->config('intranetdir') . "/installer/data/$self->{dbms}/sysprefs.sql";
+    unshift(@fnames, $globalsysprefs);
     foreach my $file (@fnames) {
         #      warn $file;
         undef $/;
     foreach my $file (@fnames) {
         #      warn $file;
         undef $/;
@@ -427,21 +345,17 @@ sub load_sql_in_order {
     return ($fwk_language, \@list);
 }
 
     return ($fwk_language, \@list);
 }
 
-=head2 set_marcflavour_syspref 
-
-=over 4
-
-$installer->set_marcflavour_syspref($marcflavour);
+=head2 set_marcflavour_syspref
 
 
-=back
+  $installer->set_marcflavour_syspref($marcflavour);
 
 Set the 'marcflavour' system preference.  The incoming
 C<$marcflavour> references to a subdirectory of
 installer/data/$dbms/$lang/marcflavour, and is
 
 Set the 'marcflavour' system preference.  The incoming
 C<$marcflavour> references to a subdirectory of
 installer/data/$dbms/$lang/marcflavour, and is
-normalized to MARC21 or UNIMARC.
+normalized to MARC21, UNIMARC or NORMARC.
 
 FIXME: this method assumes that the MARC flavour will be either
 
 FIXME: this method assumes that the MARC flavour will be either
-MARC21 or UNIMARC.
+MARC21, UNIMARC or NORMARC.
 
 =cut
 
 
 =cut
 
@@ -453,49 +367,17 @@ sub set_marcflavour_syspref {
     # marc_cleaned finds the marcflavour, without the variant.
     my $marc_cleaned = 'MARC21';
     $marc_cleaned = 'UNIMARC' if $marcflavour =~ /unimarc/i;
     # marc_cleaned finds the marcflavour, without the variant.
     my $marc_cleaned = 'MARC21';
     $marc_cleaned = 'UNIMARC' if $marcflavour =~ /unimarc/i;
+    $marc_cleaned = 'NORMARC' if $marcflavour =~ /normarc/i;
     my $request =
         $self->{'dbh'}->prepare(
     my $request =
         $self->{'dbh'}->prepare(
-          "INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('marcflavour','$marc_cleaned','Define global MARC flavor (MARC21 or UNIMARC) used for character encoding','MARC21|UNIMARC','Choice');"
+          "INSERT IGNORE INTO `systempreferences` (variable,value,explanation,options,type) VALUES('marcflavour','$marc_cleaned','Define global MARC flavor (MARC21, UNIMARC or NORMARC) used for character encoding','MARC21|UNIMARC|NORMARC','Choice');"
         );
     $request->execute;
 }
 
         );
     $request->execute;
 }
 
-=head2 set_indexing_engine 
-
-=over 4
-
-$installer->set_indexing_engine($nozebra);
-
-=back
-
-Sets system preferences related to the indexing
-engine.  The C<$nozebra> argument is a boolean;
-if true, turn on NoZebra mode and turn off QueryFuzzy,
-QueryWeightFields, and QueryStemming.  If false, turn
-off NoZebra mode (i.e., use the Zebra search engine).
-
-=cut
-
-sub set_indexing_engine {
-    my $self = shift;
-    my $nozebra = shift;
-
-    if ($nozebra) {
-        $self->{'dbh'}->do("UPDATE systempreferences SET value=1 WHERE variable='NoZebra'");
-        $self->{'dbh'}->do("UPDATE systempreferences SET value=0 WHERE variable in ('QueryFuzzy','QueryWeightFields','QueryStemming')");
-    } else {
-        $self->{'dbh'}->do("UPDATE systempreferences SET value=0 WHERE variable='NoZebra'");
-    }
-
-}
-
 =head2 set_version_syspref
 
 =head2 set_version_syspref
 
-=over 4
-
-$installer->set_version_syspref();
-
-=back
+  $installer->set_version_syspref();
 
 Set or update the 'Version' system preference to the current
 Koha software version.
 
 Set or update the 'Version' system preference to the current
 Koha software version.
@@ -522,24 +404,20 @@ sub set_version_syspref {
 
 =head2 load_sql
 
 
 =head2 load_sql
 
-=over 4
-
-my $error = $installer->load_sql($filename);
-
-=back
+  my $error = $installer->load_sql($filename);
 
 Runs a the specified SQL using the DB's command-line
 SQL tool, and returns any strings sent to STDERR
 by the command-line tool.
 
 
 Runs a the specified SQL using the DB's command-line
 SQL tool, and returns any strings sent to STDERR
 by the command-line tool.
 
-FIXME: there has been a long-standing desire to
-       replace this with an SQL loader that goes
-       through DBI; partly for portability issues
-       and partly to improve error handling.
+B<FIXME:> there has been a long-standing desire to
+replace this with an SQL loader that goes
+through DBI; partly for portability issues
+and partly to improve error handling.
 
 
-FIXME: even using the command-line loader, some more
-       basic error handling should be added - deal
-       with missing files, e.g.
+B<FIXME:> even using the command-line loader, some more
+basic error handling should be added - deal
+with missing files, e.g.
 
 =cut
 
 
 =cut
 
@@ -550,16 +428,25 @@ sub load_sql {
     my $datadir = C4::Context->config('intranetdir') . "/installer/data/$self->{dbms}";
     my $error;
     my $strcmd;
     my $datadir = C4::Context->config('intranetdir') . "/installer/data/$self->{dbms}";
     my $error;
     my $strcmd;
+    my $cmd;
     if ( $self->{dbms} eq 'mysql' ) {
     if ( $self->{dbms} eq 'mysql' ) {
-        $strcmd = "mysql "
+        $cmd = qx(which mysql 2>/dev/null || whereis mysql 2>/dev/null);
+        chomp $cmd;
+        $cmd = $1 if ($cmd && $cmd =~ /^(.+?)[\r\n]+$/);
+        $cmd = 'mysql' if (!$cmd || !-x $cmd);
+        $strcmd = "$cmd "
             . ( $self->{hostname} ? " -h $self->{hostname} " : "" )
             . ( $self->{port}     ? " -P $self->{port} "     : "" )
             . ( $self->{user}     ? " -u $self->{user} "     : "" )
             . ( $self->{password} ? " -p'$self->{password}'"   : "" )
             . " $self->{dbname} ";
             . ( $self->{hostname} ? " -h $self->{hostname} " : "" )
             . ( $self->{port}     ? " -P $self->{port} "     : "" )
             . ( $self->{user}     ? " -u $self->{user} "     : "" )
             . ( $self->{password} ? " -p'$self->{password}'"   : "" )
             . " $self->{dbname} ";
-        $error = qx($strcmd <$filename 2>&1 1>/dev/null);
+        $error = qx($strcmd --default-character-set=utf8 <$filename 2>&1 1>/dev/null);
     } elsif ( $self->{dbms} eq 'Pg' ) {
     } elsif ( $self->{dbms} eq 'Pg' ) {
-        $strcmd = "psql "
+        $cmd = qx(which psql 2>/dev/null || whereis psql 2>/dev/null);
+        chomp $cmd;
+        $cmd = $1 if ($cmd && $cmd =~ /^(.+?)[\r\n]+$/);
+        $cmd = 'psql' if (!$cmd || !-x $cmd);
+        $strcmd = "$cmd "
             . ( $self->{hostname} ? " -h $self->{hostname} " : "" )
             . ( $self->{port}     ? " -p $self->{port} "     : "" )
             . ( $self->{user}     ? " -U $self->{user} "     : "" )
             . ( $self->{hostname} ? " -h $self->{hostname} " : "" )
             . ( $self->{port}     ? " -p $self->{port} "     : "" )
             . ( $self->{user}     ? " -U $self->{user} "     : "" )
@@ -567,19 +454,20 @@ sub load_sql {
             . " $self->{dbname} ";                        # Therefore, be sure to run 'trust' on localhost in pg_hba.conf -fbcit
         $error = qx($strcmd -f $filename 2>&1 1>/dev/null);
         # Be sure to set 'client_min_messages = error' in postgresql.conf
             . " $self->{dbname} ";                        # Therefore, be sure to run 'trust' on localhost in pg_hba.conf -fbcit
         $error = qx($strcmd -f $filename 2>&1 1>/dev/null);
         # Be sure to set 'client_min_messages = error' in postgresql.conf
-        # so that only true errors are returned to stderr or else the installer will 
+        # so that only true errors are returned to stderr or else the installer will
         # report the import a failure although it really succeded -fbcit
     }
         # report the import a failure although it really succeded -fbcit
     }
+#   errors thrown while loading installer data should be logged
+    if($error) {
+      warn "C4::Installer::load_sql returned the following errors while attempting to load $filename:\n";
+      warn "$error";
+    }
     return $error;
 }
 
 =head2 get_file_path_from_name
 
     return $error;
 }
 
 =head2 get_file_path_from_name
 
-=over 4
-
-my $filename = $installer->get_file_path_from_name('script_name');
-
-=back
+  my $filename = $installer->get_file_path_from_name('script_name');
 
 searches through the set of known SQL scripts and finds the fully
 qualified path name for the script that mathches the input.
 
 searches through the set of known SQL scripts and finds the fully
 qualified path name for the script that mathches the input.
@@ -594,7 +482,7 @@ sub get_file_path_from_name {
     my $partialname = shift;
 
     my $lang = 'en'; # FIXME: how do I know what language I want?
     my $partialname = shift;
 
     my $lang = 'en'; # FIXME: how do I know what language I want?
-    
+
     my ($defaulted_to_en, $list) = $self->sample_data_sql_list($lang);
     # warn( Data::Dumper->Dump( [ $list ], [ 'list' ] ) );
 
     my ($defaulted_to_en, $list) = $self->sample_data_sql_list($lang);
     # warn( Data::Dumper->Dump( [ $list ], [ 'list' ] ) );
 
@@ -621,7 +509,7 @@ sub get_file_path_from_name {
 C4::Installer is a refactoring of logic originally from installer/installer.pl, which was
 originally written by Henri-Damien Laurant.
 
 C4::Installer is a refactoring of logic originally from installer/installer.pl, which was
 originally written by Henri-Damien Laurant.
 
-Koha Developement team <info@koha.org>
+Koha Development Team <http://koha-community.org/>
 
 Galen Charlton <galen.charlton@liblime.com>
 
 
 Galen Charlton <galen.charlton@liblime.com>