X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FContext.pm;h=926c1a5b8bb0386b4e22e3221f031310bace275b;hb=6843f5a346da3d0c0e55b7168750190c9194297b;hp=4a0564cd7f5caad56453e87460d1f65bf3825f1f;hpb=bf37fd8269e068469a69b607ce67091608ab9f02;p=srvgit diff --git a/C4/Context.pm b/C4/Context.pm index 4a0564cd7f..926c1a5b8b 100644 --- a/C4/Context.pm +++ b/C4/Context.pm @@ -12,45 +12,71 @@ package C4::Context; # 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 warnings; use vars qw($VERSION $AUTOLOAD $context @context_stack); BEGIN { if ($ENV{'HTTP_USER_AGENT'}) { require CGI::Carp; + # FIXME for future reference, CGI::Carp doc says + # "Note that fatalsToBrowser does not work with mod_perl version 2.0 and higher." import CGI::Carp qw(fatalsToBrowser); sub handle_errors { - my $msg = shift; - my $debug_level = C4::Context->preference("DebugLevel"); - + my $msg = shift; + my $debug_level; + eval {C4::Context->dbh();}; + if ($@){ + $debug_level = 1; + } + else { + $debug_level = C4::Context->preference("DebugLevel"); + } + + print q( + + Koha Error + + ); if ($debug_level eq "2"){ # debug 2 , print extra info too. my %versions = get_versions(); # a little example table with various version info"; print " -

debug level $debug_level

-

Got an error: $msg

+

Koha error

+

The following fatal error has occurred:

+
$msg
- - - - - + + + + + +
Apache $versions{apacheVersion}
Koha $versions{kohaVersion}
MySQL $versions{mysqlVersion}
OS $versions{osVersion}
Perl $versions{perlVersion}
Apache $versions{apacheVersion}
Koha $versions{kohaVersion}
Koha DB $versions{kohaDbVersion}
MySQL $versions{mysqlVersion}
OS $versions{osVersion}
Perl $versions{perlVersion}
"; } elsif ($debug_level eq "1"){ - print "

debug level $debug_level

"; - print "

Got an error: $msg

"; + print " +

Koha error

+

The following fatal error has occurred:

+
$msg
"; } else { - print "production mode - trapped fatal"; + print "

production mode - trapped fatal error

"; } - } - CGI::Carp->set_message(\&handle_errors); + print ""; + } + #CGI::Carp::set_message(\&handle_errors); + ## give a stack backtrace if KOHA_BACKTRACES is set + ## can't rely on DebugLevel for this, as we're not yet connected + if ($ENV{KOHA_BACKTRACES}) { + $main::SIG{__DIE__} = \&CGI::Carp::confess; + } } # else there is no browser to send fatals to! $VERSION = '3.00.00.036'; } @@ -59,6 +85,8 @@ use DBI; use ZOOM; use XML::Simple; use C4::Boolean; +use C4::Debug; +use POSIX (); =head1 NAME @@ -164,17 +192,14 @@ $context = undef; # Initially, no context is set =cut sub KOHAVERSION { - my $cgidir = C4::Context->intranetdir ."/cgi-bin"; - - # 2 cases here : on CVS install, $cgidir does not need a /cgi-bin - # on a standard install, /cgi-bin need to be added. - # test one, then the other - # FIXME - is this all really necessary? - unless (opendir(DIR, "$cgidir/cataloguing/value_builder")) { - $cgidir = C4::Context->intranetdir; - closedir(DIR); - } + my $cgidir = C4::Context->intranetdir; + # Apparently the GIT code does not run out of a CGI-BIN subdirectory + # but distribution code does? (Stan, 1jan08) + if(-d $cgidir . "/cgi-bin"){ + my $cgidir .= "/cgi-bin"; + } + do $cgidir."/kohaversion.pl" || die "NO $cgidir/kohaversion.pl"; return kohaversion(); } @@ -208,7 +233,7 @@ Returns undef in case of error. =cut sub read_config_file { # Pass argument naming config file to read - my $koha = XMLin(shift, keyattr => ['id'], forcearray => ['listen', 'server', 'serverinfo']); + my $koha = XMLin(shift, keyattr => ['id'], forcearray => ['listen', 'server', 'serverinfo'], suppressempty => ''); return $koha; # Return value: ref-to-hash holding the configuration } @@ -228,15 +253,21 @@ sub db_scheme2dbi { } sub import { - my $package = shift; - my $conf_fname = shift; # Config file name - my $context; - - # Create a new context from the given config file name, if - # any, then set it as the current context. - $context = new C4::Context($conf_fname); - return undef if !defined($context); - $context->set_context; + # Create the default context ($C4::Context::Context) + # the first time the module is called + # (a config file can be optionaly passed) + + # default context allready exists? + return if $context; + + # no ? so load it! + my ($pkg,$config_file) = @_ ; + my $new_ctx = __PACKAGE__->new($config_file); + return unless $new_ctx; + + # if successfully loaded, use it by default + $new_ctx->set_context; + 1; } =item new @@ -415,32 +446,44 @@ sub ModZebrations { =item preference - $sys_preference = C4::Context->preference("some_variable"); + $sys_preference = C4::Context->preference('some_variable'); Looks up the value of the given system preference in the systempreferences table of the Koha database, and returns it. If the -variable is not set, or in case of error, returns the undefined value. +variable is not set or does not exist, undef is returned. + +In case of an error, this may return 0. + +Note: It is impossible to tell the difference between system +preferences which do not exist, and those whose values are set to NULL +with this method. =cut -#' -# FIXME - The preferences aren't likely to change over the lifetime of -# the script (and things might break if they did change), so perhaps -# this function should cache the results it finds. -sub preference -{ +# FIXME: running this under mod_perl will require a means of +# flushing the caching mechanism. + +my %sysprefs; + +sub preference { my $self = shift; - my $var = shift; # The system preference to return - my $retval; # Return value - my $dbh = C4::Context->dbh or return 0; + my $var = shift; # The system preference to return + + if (exists $sysprefs{$var}) { + return $sysprefs{$var}; + } + + my $dbh = C4::Context->dbh or return 0; + # Look up systempreferences.variable==$var - $retval = $dbh->selectrow_array(<selectrow_array( $sql, {}, $var ); + return $sysprefs{$var}; } sub boolean_preference ($) { @@ -450,6 +493,51 @@ sub boolean_preference ($) { return defined($it)? C4::Boolean::true_p($it): undef; } +=item clear_syspref_cache + + C4::Context->clear_syspref_cache(); + + cleans the internal cache of sysprefs. Please call this method if + you update the systempreferences table. Otherwise, your new changes + will not be seen by this process. + +=cut + +sub clear_syspref_cache { + %sysprefs = (); +} + +=item set_preference + + C4::Context->set_preference( $variable, $value ); + + This updates a preference's value both in the systempreferences table and in + the sysprefs cache. + +=cut + +sub set_preference { + my $self = shift; + my $var = shift; + my $value = shift; + + my $dbh = C4::Context->dbh or return 0; + + my $type = $dbh->selectrow_array( "SELECT type FROM systempreferences WHERE variable = ?", {}, $var ); + + $value = 0 if ( $type && $type eq 'YesNo' && $value eq '' ); + + my $sth = $dbh->prepare( " + INSERT INTO systempreferences + ( variable, value ) + VALUES( ?, ? ) + ON DUPLICATE KEY UPDATE value = VALUES(value) + " ); + + $sth->execute( $var, $value ); + $sth->finish; +} + # AUTOLOAD # This implements C4::Config->foo, and simply returns # C4::Context->config("foo"), as described in the documentation for @@ -494,10 +582,18 @@ sub Zconn { my $auth=shift; my $piggyback=shift; my $syntax=shift; - if ( defined($context->{"Zconn"}->{$server}) && !$context->{"Zconn"}->{$server}->exception() ) { + if ( defined($context->{"Zconn"}->{$server}) && (0 == $context->{"Zconn"}->{$server}->errcode()) ) { return $context->{"Zconn"}->{$server}; # No connection object or it died. Create one. }else { + # release resources if we're closing a connection and making a new one + # FIXME: this needs to be smarter -- an error due to a malformed query or + # a missing index does not necessarily require us to close the connection + # and make a new one, particularly for a batch job. However, at + # first glance it does not look like there's a way to easily check + # the basic health of a ZOOM::Connection + $context->{"Zconn"}->{$server}->destroy() if defined($context->{"Zconn"}->{$server}); + $context->{"Zconn"}->{$server} = &_new_Zconn($server,$async,$auth,$piggyback,$syntax); return $context->{"Zconn"}->{$server}; } @@ -583,32 +679,34 @@ sub _new_Zconn { sub _new_dbh { -### $context - ##correct name for db_schme + ## $context + ## correct name for db_schme my $db_driver; if ($context->config("db_scheme")){ - $db_driver=db_scheme2dbi($context->config("db_scheme")); + $db_driver=db_scheme2dbi($context->config("db_scheme")); }else{ - $db_driver="mysql"; + $db_driver="mysql"; } my $db_name = $context->config("database"); my $db_host = $context->config("hostname"); - my $db_port = $context->config("port"); - $db_port = "" unless defined $db_port; + my $db_port = $context->config("port") || ''; my $db_user = $context->config("user"); my $db_passwd = $context->config("pass"); # MJR added or die here, as we can't work without dbh my $dbh= DBI->connect("DBI:$db_driver:dbname=$db_name;host=$db_host;port=$db_port", - $db_user, $db_passwd) or die $DBI::errstr; + $db_user, $db_passwd) or die $DBI::errstr; + my $tz = $ENV{TZ}; if ( $db_driver eq 'mysql' ) { # Koha 3.0 is utf-8, so force utf8 communication between mySQL and koha, whatever the mysql default config. # this is better than modifying my.cnf (and forcing all communications to be in utf8) $dbh->{'mysql_enable_utf8'}=1; #enable $dbh->do("set NAMES 'utf8'"); + ($tz) and $dbh->do(qq(SET time_zone = "$tz")); } elsif ( $db_driver eq 'Pg' ) { $dbh->do( "set client_encoding = 'UTF8';" ); + ($tz) and $dbh->do(qq(SET TIME ZONE = "$tz")); } return $dbh; } @@ -634,9 +732,8 @@ sub dbh my $self = shift; my $sth; - if (defined($context->{"dbh"})) { - $sth=$context->{"dbh"}->prepare("select 1"); - return $context->{"dbh"} if (defined($sth->execute)); + if (defined($context->{"dbh"}) && $context->{"dbh"}->ping()) { + return $context->{"dbh"}; } # No database handle or it died . Create one. @@ -800,7 +897,6 @@ sub _new_stopwords my $sth = $dbh->prepare("select word from stopwords"); $sth->execute; while (my $stopword = $sth->fetchrow_array) { - my $retval = {}; $stopwordlist->{$stopword} = uc($stopword); } $stopwordlist->{A} = "A" unless $stopwordlist; @@ -811,20 +907,17 @@ sub _new_stopwords C4::Context->userenv; -Builds a hash for user environment variables. +Retrieves a hash for user environment variables. This hash shall be cached for future use: if you call Cuserenv> twice, you will get the same hash without real DB access -set_userenv is called in Auth.pm - =cut #' -sub userenv -{ +sub userenv { my $var = $context->{"activeuser"}; - return $context->{"userenv"}->{$var} if (defined $context->{"userenv"}->{$var}); + return $context->{"userenv"}->{$var} if (defined $var and defined $context->{"userenv"}->{$var}); # insecure=1 management if ($context->{"dbh"} && $context->preference('insecure')) { my %insecure; @@ -837,7 +930,7 @@ sub userenv $insecure{emailaddress} = 'test@mode.insecure.com'; return \%insecure; } else { - return 0; + return; } } @@ -845,17 +938,14 @@ sub userenv C4::Context->set_userenv($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $userflags, $emailaddress); -Informs a hash for user environment variables. - -This hash shall be cached for future use: if you call -Cuserenv> twice, you will get the same hash without real DB access +Establish a hash of user environment variables. set_userenv is called in Auth.pm =cut #' -sub set_userenv{ +sub set_userenv { my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter)= @_; my $var=$context->{"activeuser"}; my $cell = { @@ -864,36 +954,40 @@ sub set_userenv{ "cardnumber" => $usercnum, "firstname" => $userfirstname, "surname" => $usersurname, -#possibly a law problem + #possibly a law problem "branch" => $userbranch, "branchname" => $branchname, "flags" => $userflags, - "emailaddress" => $emailaddress, - "branchprinter" => $branchprinter + "emailaddress" => $emailaddress, + "branchprinter" => $branchprinter }; $context->{userenv}->{$var} = $cell; return $cell; } -sub set_shelves_userenv ($) { - my $lists = shift or return undef; +sub set_shelves_userenv ($$) { + my ($type, $shelves) = @_ or return undef; my $activeuser = $context->{activeuser} or return undef; - $context->{userenv}->{$activeuser}->{shelves} = $lists; - # die "set_shelves_userenv: $lists"; + $context->{userenv}->{$activeuser}->{barshelves} = $shelves if $type eq 'bar'; + $context->{userenv}->{$activeuser}->{pubshelves} = $shelves if $type eq 'pub'; + $context->{userenv}->{$activeuser}->{totshelves} = $shelves if $type eq 'tot'; } + sub get_shelves_userenv () { my $active; unless ($active = $context->{userenv}->{$context->{activeuser}}) { - warn "get_shelves_userenv cannot retrieve context->{userenv}->{context->{activeuser}}"; + $debug and warn "get_shelves_userenv cannot retrieve context->{userenv}->{context->{activeuser}}"; return undef; } - my $lists = $active->{shelves} or return undef;# die "get_shelves_userenv: activeenv has no ->{shelves}"; - return $lists; + my $totshelves = $active->{totshelves} or undef; + my $pubshelves = $active->{pubshelves} or undef; + my $barshelves = $active->{barshelves} or undef; + return ($totshelves, $pubshelves, $barshelves); } =item _new_userenv - C4::Context->_new_userenv($session); + C4::Context->_new_userenv($session); # FIXME: This calling style is wrong for what looks like an _internal function Builds a hash for user environment variables. @@ -907,7 +1001,7 @@ _new_userenv is called in Auth.pm #' sub _new_userenv { - shift; + shift; # Useless except it compensates for bad calling style my ($sessionID)= @_; $context->{"activeuser"}=$sessionID; } @@ -942,14 +1036,18 @@ Gets various version info, for core Koha packages, Currently called from carp ha # A little example sub to show more debugging info for CGI::Carp sub get_versions { my %versions; - $versions{kohaVersion} = C4::Context->config("kohaversion"); - $versions{osVersion} = `uname -a`; + $versions{kohaVersion} = KOHAVERSION(); + $versions{kohaDbVersion} = C4::Context->preference('version'); + $versions{osVersion} = join(" ", POSIX::uname()); $versions{perlVersion} = $]; - $versions{mysqlVersion} = `mysql -V`; - $versions{apacheVersion} = `httpd -v`; - $versions{apacheVersion} = `httpd2 -v` unless $versions{apacheVersion} ; - $versions{apacheVersion} = `apache2 -v` unless $versions{apacheVersion} ; - $versions{apacheVersion} = `/usr/sbin/apache2 -v` unless $versions{apacheVersion} ; + { + no warnings qw(exec); # suppress warnings if unable to find a program in $PATH + $versions{mysqlVersion} = `mysql -V`; + $versions{apacheVersion} = `httpd -v`; + $versions{apacheVersion} = `httpd2 -v` unless $versions{apacheVersion} ; + $versions{apacheVersion} = `apache2 -v` unless $versions{apacheVersion} ; + $versions{apacheVersion} = `/usr/sbin/apache2 -v` unless $versions{apacheVersion} ; + } return %versions; }