| 1 | | | | | package C4::Context; |
| 2 | | | | | # Copyright 2002 Katipo Communications |
| 3 | | | | | # |
| 4 | | | | | # This file is part of Koha. |
| 5 | | | | | # |
| 6 | | | | | # Koha is free software; you can redistribute it and/or modify it |
| 7 | | | | | # under the terms of the GNU General Public License as published by |
| 8 | | | | | # the Free Software Foundation; either version 3 of the License, or |
| 9 | | | | | # (at your option) any later version. |
| 10 | | | | | # |
| 11 | | | | | # Koha is distributed in the hope that it will be useful, but |
| 12 | | | | | # WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | | | | | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | | | | | # GNU General Public License for more details. |
| 15 | | | | | # |
| 16 | | | | | # You should have received a copy of the GNU General Public License |
| 17 | | | | | # along with Koha; if not, see <http://www.gnu.org/licenses>. |
| 18 | | | | | |
| 19 | | | | | use strict; |
| 20 | | | | | use warnings; |
| 21 | | | | | use vars qw($VERSION $AUTOLOAD $context @context_stack $servers $memcached $ismemcached); |
| 22 | | | | | BEGIN { |
| 23 | | | | | if ($ENV{'HTTP_USER_AGENT'}) { |
| 24 | | | | | require CGI::Carp; |
| 25 | | | | | # FIXME for future reference, CGI::Carp doc says |
| 26 | | | | | # "Note that fatalsToBrowser does not work with mod_perl version 2.0 and higher." |
| 27 | | | | | import CGI::Carp qw(fatalsToBrowser); |
| 28 | | | | | sub handle_errors { |
| 29 | | | | | my $msg = shift; |
| 30 | | | | | my $debug_level; |
| 31 | | | | | eval {C4::Context->dbh();}; |
| 32 | | | | | if ($@){ |
| 33 | | | | | $debug_level = 1; |
| 34 | | | | | } |
| 35 | | | | | else { |
| 36 | | | | | $debug_level = C4::Context->preference("DebugLevel"); |
| 37 | | | | | } |
| 38 | | | | | |
| 39 | | | | | print q(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
| 40 | | | | | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| 41 | | | | | <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> |
| 42 | | | | | <head><title>Koha Error</title></head> |
| 43 | | | | | <body> |
| 44 | | | | | ); |
| 45 | | | | | if ($debug_level eq "2"){ |
| 46 | | | | | # debug 2 , print extra info too. |
| 47 | | | | | my %versions = get_versions(); |
| 48 | | | | | |
| 49 | | | | | # a little example table with various version info"; |
| 50 | | | | | print " |
| 51 | | | | | <h1>Koha error</h1> |
| 52 | | | | | <p>The following fatal error has occurred:</p> |
| 53 | | | | | <pre><code>$msg</code></pre> |
| 54 | | | | | <table> |
| 55 | | | | | <tr><th>Apache</th><td> $versions{apacheVersion}</td></tr> |
| 56 | | | | | <tr><th>Koha</th><td> $versions{kohaVersion}</td></tr> |
| 57 | | | | | <tr><th>Koha DB</th><td> $versions{kohaDbVersion}</td></tr> |
| 58 | | | | | <tr><th>MySQL</th><td> $versions{mysqlVersion}</td></tr> |
| 59 | | | | | <tr><th>OS</th><td> $versions{osVersion}</td></tr> |
| 60 | | | | | <tr><th>Perl</th><td> $versions{perlVersion}</td></tr> |
| 61 | | | | | </table>"; |
| 62 | | | | | |
| 63 | | | | | } elsif ($debug_level eq "1"){ |
| 64 | | | | | print " |
| 65 | | | | | <h1>Koha error</h1> |
| 66 | | | | | <p>The following fatal error has occurred:</p> |
| 67 | | | | | <pre><code>$msg</code></pre>"; |
| 68 | | | | | } else { |
| 69 | | | | | print "<p>production mode - trapped fatal error</p>"; |
| 70 | | | | | } |
| 71 | | | | | print "</body></html>"; |
| 72 | | | | | } |
| 73 | | | | | #CGI::Carp::set_message(\&handle_errors); |
| 74 | | | | | ## give a stack backtrace if KOHA_BACKTRACES is set |
| 75 | | | | | ## can't rely on DebugLevel for this, as we're not yet connected |
| 76 | | | | | if ($ENV{KOHA_BACKTRACES}) { |
| 77 | | | | | $main::SIG{__DIE__} = \&CGI::Carp::confess; |
| 78 | | | | | } |
| 79 | | | | | } # else there is no browser to send fatals to! |
| 80 | | | | | |
| 81 | | | | | # Check if there are memcached servers set |
| 82 | | | | | $servers = $ENV{'MEMCACHED_SERVERS'}; |
| 83 | | | | | if ($servers) { |
| 84 | | | | | # Load required libraries and create the memcached object |
| 85 | | | | | require Cache::Memcached; |
| 86 | | | | | $memcached = Cache::Memcached->new({ |
| 87 | | | | | servers => [ $servers ], |
| 88 | | | | | debug => 0, |
| 89 | | | | | compress_threshold => 10_000, |
| 90 | | | | | expire_time => 600, |
| 91 | | | | | namespace => $ENV{'MEMCACHED_NAMESPACE'} || 'koha' |
| 92 | | | | | }); |
| 93 | | | | | # Verify memcached available (set a variable and test the output) |
| 94 | | | | | $ismemcached = $memcached->set('ismemcached','1'); |
| 95 | | | | | } |
| 96 | | | | | |
| 97 | | | | | $VERSION = '3.07.00.049'; |
| 98 | | | | | } |
| 99 | | | | | |
| 100 | | | | | use Encode; |
| 101 | | | | | use ZOOM; |
| 102 | | | | | use XML::Simple; |
| 103 | | | | | use POSIX (); |
| 104 | | | | | use DateTime::TimeZone; |
| 105 | | | | | use Module::Load::Conditional qw(can_load); |
| 106 | | | | | use Carp; |
| 107 | | | | | |
| 108 | | | | | use C4::Boolean; |
| 109 | | | | | use C4::Debug; |
| 110 | | | | | use Koha; |
| 111 | | | | | use Koha::Config::SysPrefs; |
| 112 | | | | | |
| 113 | | | | | =head1 NAME |
| 114 | | | | | |
| 115 | | | | | C4::Context - Maintain and manipulate the context of a Koha script |
| 116 | | | | | |
| 117 | | | | | =head1 SYNOPSIS |
| 118 | | | | | |
| 119 | | | | | use C4::Context; |
| 120 | | | | | |
| 121 | | | | | use C4::Context("/path/to/koha-conf.xml"); |
| 122 | | | | | |
| 123 | | | | | $config_value = C4::Context->config("config_variable"); |
| 124 | | | | | |
| 125 | | | | | $koha_preference = C4::Context->preference("preference"); |
| 126 | | | | | |
| 127 | | | | | $db_handle = C4::Context->dbh; |
| 128 | | | | | |
| 129 | | | | | $Zconn = C4::Context->Zconn; |
| 130 | | | | | |
| 131 | | | | | =head1 DESCRIPTION |
| 132 | | | | | |
| 133 | | | | | When a Koha script runs, it makes use of a certain number of things: |
| 134 | | | | | configuration settings in F</etc/koha/koha-conf.xml>, a connection to the Koha |
| 135 | | | | | databases, and so forth. These things make up the I<context> in which |
| 136 | | | | | the script runs. |
| 137 | | | | | |
| 138 | | | | | This module takes care of setting up the context for a script: |
| 139 | | | | | figuring out which configuration file to load, and loading it, opening |
| 140 | | | | | a connection to the right database, and so forth. |
| 141 | | | | | |
| 142 | | | | | Most scripts will only use one context. They can simply have |
| 143 | | | | | |
| 144 | | | | | use C4::Context; |
| 145 | | | | | |
| 146 | | | | | at the top. |
| 147 | | | | | |
| 148 | | | | | Other scripts may need to use several contexts. For instance, if a |
| 149 | | | | | library has two databases, one for a certain collection, and the other |
| 150 | | | | | for everything else, it might be necessary for a script to use two |
| 151 | | | | | different contexts to search both databases. Such scripts should use |
| 152 | | | | | the C<&set_context> and C<&restore_context> functions, below. |
| 153 | | | | | |
| 154 | | | | | By default, C4::Context reads the configuration from |
| 155 | | | | | F</etc/koha/koha-conf.xml>. This may be overridden by setting the C<$KOHA_CONF> |
| 156 | | | | | environment variable to the pathname of a configuration file to use. |
| 157 | | | | | |
| 158 | | | | | =head1 METHODS |
| 159 | | | | | |
| 160 | | | | | =cut |
| 161 | | | | | |
| 162 | | | | | #' |
| 163 | | | | | # In addition to what is said in the POD above, a Context object is a |
| 164 | | | | | # reference-to-hash with the following fields: |
| 165 | | | | | # |
| 166 | | | | | # config |
| 167 | | | | | # A reference-to-hash whose keys and values are the |
| 168 | | | | | # configuration variables and values specified in the config |
| 169 | | | | | # file (/etc/koha/koha-conf.xml). |
| 170 | | | | | # dbh |
| 171 | | | | | # A handle to the appropriate database for this context. |
| 172 | | | | | # dbh_stack |
| 173 | | | | | # Used by &set_dbh and &restore_dbh to hold other database |
| 174 | | | | | # handles for this context. |
| 175 | | | | | # Zconn |
| 176 | | | | | # A connection object for the Zebra server |
| 177 | | | | | |
| 178 | | | | | # Koha's main configuration file koha-conf.xml |
| 179 | | | | | # is searched for according to this priority list: |
| 180 | | | | | # |
| 181 | | | | | # 1. Path supplied via use C4::Context '/path/to/koha-conf.xml' |
| 182 | | | | | # 2. Path supplied in KOHA_CONF environment variable. |
| 183 | | | | | # 3. Path supplied in INSTALLED_CONFIG_FNAME, as long |
| 184 | | | | | # as value has changed from its default of |
| 185 | | | | | # '__KOHA_CONF_DIR__/koha-conf.xml', as happens |
| 186 | | | | | # when Koha is installed in 'standard' or 'single' |
| 187 | | | | | # mode. |
| 188 | | | | | # 4. Path supplied in CONFIG_FNAME. |
| 189 | | | | | # |
| 190 | | | | | # The first entry that refers to a readable file is used. |
| 191 | | | | | |
| 192 | | | | | use constant CONFIG_FNAME => "/etc/koha/koha-conf.xml"; |
| 193 | | | | | # Default config file, if none is specified |
| 194 | | | | | |
| 195 | | | | | my $INSTALLED_CONFIG_FNAME = '__KOHA_CONF_DIR__/koha-conf.xml'; |
| 196 | | | | | # path to config file set by installer |
| 197 | | | | | # __KOHA_CONF_DIR__ is set by rewrite-confg.PL |
| 198 | | | | | # when Koha is installed in 'standard' or 'single' |
| 199 | | | | | # mode. If Koha was installed in 'dev' mode, |
| 200 | | | | | # __KOHA_CONF_DIR__ is *not* rewritten; instead |
| 201 | | | | | # developers should set the KOHA_CONF environment variable |
| 202 | | | | | |
| 203 | | | | | $context = undef; # Initially, no context is set |
| 204 | | | | | @context_stack = (); # Initially, no saved contexts |
| 205 | | | | | |
| 206 | | | | | |
| 207 | | | | | =head2 read_config_file |
| 208 | | | | | |
| 209 | | | | | Reads the specified Koha config file. |
| 210 | | | | | |
| 211 | | | | | Returns an object containing the configuration variables. The object's |
| 212 | | | | | structure is a bit complex to the uninitiated ... take a look at the |
| 213 | | | | | koha-conf.xml file as well as the XML::Simple documentation for details. Or, |
| 214 | | | | | here are a few examples that may give you what you need: |
| 215 | | | | | |
| 216 | | | | | The simple elements nested within the <config> element: |
| 217 | | | | | |
| 218 | | | | | my $pass = $koha->{'config'}->{'pass'}; |
| 219 | | | | | |
| 220 | | | | | The <listen> elements: |
| 221 | | | | | |
| 222 | | | | | my $listen = $koha->{'listen'}->{'biblioserver'}->{'content'}; |
| 223 | | | | | |
| 224 | | | | | The elements nested within the <server> element: |
| 225 | | | | | |
| 226 | | | | | my $ccl2rpn = $koha->{'server'}->{'biblioserver'}->{'cql2rpn'}; |
| 227 | | | | | |
| 228 | | | | | Returns undef in case of error. |
| 229 | | | | | |
| 230 | | | | | =cut |
| 231 | | | | | |
| 232 | | | | | sub read_config_file { # Pass argument naming config file to read |
| 233 | | | | | my $koha = XMLin(shift, keyattr => ['id'], forcearray => ['listen', 'server', 'serverinfo'], suppressempty => ''); |
| 234 | | | | | |
| 235 | | | | | if ($ismemcached) { |
| 236 | | | | | $memcached->set('kohaconf',$koha); |
| 237 | | | | | } |
| 238 | | | | | |
| 239 | | | | | return $koha; # Return value: ref-to-hash holding the configuration |
| 240 | | | | | } |
| 241 | | | | | |
| 242 | | | | | =head2 ismemcached |
| 243 | | | | | |
| 244 | | | | | Returns the value of the $ismemcached variable (0/1) |
| 245 | | | | | |
| 246 | | | | | =cut |
| 247 | | | | | |
| 248 | | | | | sub ismemcached { |
| 249 | | | | | return $ismemcached; |
| 250 | | | | | } |
| 251 | | | | | |
| 252 | | | | | =head2 memcached |
| 253 | | | | | |
| 254 | | | | | If $ismemcached is true, returns the $memcache variable. |
| 255 | | | | | Returns undef otherwise |
| 256 | | | | | |
| 257 | | | | | =cut |
| 258 | | | | | |
| 259 | | | | | sub memcached { |
| 260 | | | | | if ($ismemcached) { |
| 261 | | | | | return $memcached; |
| 262 | | | | | } else { |
| 263 | | | | | return; |
| 264 | | | | | } |
| 265 | | | | | } |
| 266 | | | | | |
| 267 | | | | | =head2 db_scheme2dbi |
| 268 | | | | | |
| 269 | | | | | my $dbd_driver_name = C4::Context::db_schema2dbi($scheme); |
| 270 | | | | | |
| 271 | | | | | This routines translates a database type to part of the name |
| 272 | | | | | of the appropriate DBD driver to use when establishing a new |
| 273 | | | | | database connection. It recognizes 'mysql' and 'Pg'; if any |
| 274 | | | | | other scheme is supplied it defaults to 'mysql'. |
| 275 | | | | | |
| 276 | | | | | =cut |
| 277 | | | | | |
| 278 | | | | | sub db_scheme2dbi { |
| 279 | | | | | my $scheme = shift // ''; |
| 280 | | | | | return $scheme eq 'Pg' ? $scheme : 'mysql'; |
| 281 | | | | | } |
| 282 | | | | | |
| 283 | | | | | sub import { |
| 284 | | | | | # Create the default context ($C4::Context::Context) |
| 285 | | | | | # the first time the module is called |
| 286 | | | | | # (a config file can be optionaly passed) |
| 287 | | | | | |
| 288 | | | | | # default context already exists? |
| 289 | | | | | return if $context; |
| 290 | | | | | |
| 291 | | | | | # no ? so load it! |
| 292 | | | | | my ($pkg,$config_file) = @_ ; |
| 293 | | | | | my $new_ctx = __PACKAGE__->new($config_file); |
| 294 | | | | | return unless $new_ctx; |
| 295 | | | | | |
| 296 | | | | | # if successfully loaded, use it by default |
| 297 | | | | | $new_ctx->set_context; |
| 298 | | | | | 1; |
| 299 | | | | | } |
| 300 | | | | | |
| 301 | | | | | =head2 new |
| 302 | | | | | |
| 303 | | | | | $context = new C4::Context; |
| 304 | | | | | $context = new C4::Context("/path/to/koha-conf.xml"); |
| 305 | | | | | |
| 306 | | | | | Allocates a new context. Initializes the context from the specified |
| 307 | | | | | file, which defaults to either the file given by the C<$KOHA_CONF> |
| 308 | | | | | environment variable, or F</etc/koha/koha-conf.xml>. |
| 309 | | | | | |
| 310 | | | | | It saves the koha-conf.xml values in the declared memcached server(s) |
| 311 | | | | | if currently available and uses those values until them expire and |
| 312 | | | | | re-reads them. |
| 313 | | | | | |
| 314 | | | | | C<&new> does not set this context as the new default context; for |
| 315 | | | | | that, use C<&set_context>. |
| 316 | | | | | |
| 317 | | | | | =cut |
| 318 | | | | | |
| 319 | | | | | #' |
| 320 | | | | | # Revision History: |
| 321 | | | | | # 2004-08-10 A. Tarallo: Added check if the conf file is not empty |
| 322 | | | | | sub new { |
| 323 | | | | | my $class = shift; |
| 324 | | | | | my $conf_fname = shift; # Config file to load |
| 325 | | | | | my $self = {}; |
| 326 | | | | | |
| 327 | | | | | # check that the specified config file exists and is not empty |
| 328 | | | | | undef $conf_fname unless |
| 329 | | | | | (defined $conf_fname && -s $conf_fname); |
| 330 | | | | | # Figure out a good config file to load if none was specified. |
| 331 | | | | | if (!defined($conf_fname)) |
| 332 | | | | | { |
| 333 | | | | | # If the $KOHA_CONF environment variable is set, use |
| 334 | | | | | # that. Otherwise, use the built-in default. |
| 335 | | | | | if (exists $ENV{"KOHA_CONF"} and $ENV{'KOHA_CONF'} and -s $ENV{"KOHA_CONF"}) { |
| 336 | | | | | $conf_fname = $ENV{"KOHA_CONF"}; |
| 337 | | | | | } elsif ($INSTALLED_CONFIG_FNAME !~ /__KOHA_CONF_DIR/ and -s $INSTALLED_CONFIG_FNAME) { |
| 338 | | | | | # NOTE: be careful -- don't change __KOHA_CONF_DIR in the above |
| 339 | | | | | # regex to anything else -- don't want installer to rewrite it |
| 340 | | | | | $conf_fname = $INSTALLED_CONFIG_FNAME; |
| 341 | | | | | } elsif (-s CONFIG_FNAME) { |
| 342 | | | | | $conf_fname = CONFIG_FNAME; |
| 343 | | | | | } else { |
| 344 | | | | | warn "unable to locate Koha configuration file koha-conf.xml"; |
| 345 | | | | | return; |
| 346 | | | | | } |
| 347 | | | | | } |
| 348 | | | | | |
| 349 | | | | | if ($ismemcached) { |
| 350 | | | | | # retrieve from memcached |
| 351 | | | | | $self = $memcached->get('kohaconf'); |
| 352 | | | | | if (not defined $self) { |
| 353 | | | | | # not in memcached yet |
| 354 | | | | | $self = read_config_file($conf_fname); |
| 355 | | | | | } |
| 356 | | | | | } else { |
| 357 | | | | | # non-memcached env, read from file |
| 358 | | | | | $self = read_config_file($conf_fname); |
| 359 | | | | | } |
| 360 | | | | | |
| 361 | | | | | $self->{"config_file"} = $conf_fname; |
| 362 | | | | | warn "read_config_file($conf_fname) returned undef" if !defined($self->{"config"}); |
| 363 | | | | | return if !defined($self->{"config"}); |
| 364 | | | | | |
| 365 | | | | | $self->{"Zconn"} = undef; # Zebra Connections |
| 366 | | | | | $self->{"marcfromkohafield"} = undef; # the hash with relations between koha table fields and MARC field/subfield |
| 367 | | | | | $self->{"userenv"} = undef; # User env |
| 368 | | | | | $self->{"activeuser"} = undef; # current active user |
| 369 | | | | | $self->{"shelves"} = undef; |
| 370 | | | | | $self->{tz} = undef; # local timezone object |
| 371 | | | | | |
| 372 | | | | | bless $self, $class; |
| 373 | | | | | $self->{db_driver} = db_scheme2dbi($self->config('db_scheme')); # cache database driver |
| 374 | | | | | return $self; |
| 375 | | | | | } |
| 376 | | | | | |
| 377 | | | | | =head2 set_context |
| 378 | | | | | |
| 379 | | | | | $context = new C4::Context; |
| 380 | | | | | $context->set_context(); |
| 381 | | | | | or |
| 382 | | | | | set_context C4::Context $context; |
| 383 | | | | | |
| 384 | | | | | ... |
| 385 | | | | | restore_context C4::Context; |
| 386 | | | | | |
| 387 | | | | | In some cases, it might be necessary for a script to use multiple |
| 388 | | | | | contexts. C<&set_context> saves the current context on a stack, then |
| 389 | | | | | sets the context to C<$context>, which will be used in future |
| 390 | | | | | operations. To restore the previous context, use C<&restore_context>. |
| 391 | | | | | |
| 392 | | | | | =cut |
| 393 | | | | | |
| 394 | | | | | #' |
| 395 | | | | | sub set_context |
| 396 | | | | | { |
| 397 | | | | | my $self = shift; |
| 398 | | | | | my $new_context; # The context to set |
| 399 | | | | | |
| 400 | | | | | # Figure out whether this is a class or instance method call. |
| 401 | | | | | # |
| 402 | | | | | # We're going to make the assumption that control got here |
| 403 | | | | | # through valid means, i.e., that the caller used an instance |
| 404 | | | | | # or class method call, and that control got here through the |
| 405 | | | | | # usual inheritance mechanisms. The caller can, of course, |
| 406 | | | | | # break this assumption by playing silly buggers, but that's |
| 407 | | | | | # harder to do than doing it properly, and harder to check |
| 408 | | | | | # for. |
| 409 | | | | | if (ref($self) eq "") |
| 410 | | | | | { |
| 411 | | | | | # Class method. The new context is the next argument. |
| 412 | | | | | $new_context = shift; |
| 413 | | | | | } else { |
| 414 | | | | | # Instance method. The new context is $self. |
| 415 | | | | | $new_context = $self; |
| 416 | | | | | } |
| 417 | | | | | |
| 418 | | | | | # Save the old context, if any, on the stack |
| 419 | | | | | push @context_stack, $context if defined($context); |
| 420 | | | | | |
| 421 | | | | | # Set the new context |
| 422 | | | | | $context = $new_context; |
| 423 | | | | | } |
| 424 | | | | | |
| 425 | | | | | =head2 restore_context |
| 426 | | | | | |
| 427 | | | | | &restore_context; |
| 428 | | | | | |
| 429 | | | | | Restores the context set by C<&set_context>. |
| 430 | | | | | |
| 431 | | | | | =cut |
| 432 | | | | | |
| 433 | | | | | #' |
| 434 | | | | | sub restore_context |
| 435 | | | | | { |
| 436 | | | | | my $self = shift; |
| 437 | | | | | |
| 438 | | | | | if ($#context_stack < 0) |
| 439 | | | | | { |
| 440 | | | | | # Stack underflow. |
| 441 | | | | | die "Context stack underflow"; |
| 442 | | | | | } |
| 443 | | | | | |
| 444 | | | | | # Pop the old context and set it. |
| 445 | | | | | $context = pop @context_stack; |
| 446 | | | | | |
| 447 | | | | | # FIXME - Should this return something, like maybe the context |
| 448 | | | | | # that was current when this was called? |
| 449 | | | | | } |
| 450 | | | | | |
| 451 | | | | | =head2 config |
| 452 | | | | | |
| 453 | | | | | $value = C4::Context->config("config_variable"); |
| 454 | | | | | |
| 455 | | | | | $value = C4::Context->config_variable; |
| 456 | | | | | |
| 457 | | | | | Returns the value of a variable specified in the configuration file |
| 458 | | | | | from which the current context was created. |
| 459 | | | | | |
| 460 | | | | | The second form is more compact, but of course may conflict with |
| 461 | | | | | method names. If there is a configuration variable called "new", then |
| 462 | | | | | C<C4::Config-E<gt>new> will not return it. |
| 463 | | | | | |
| 464 | | | | | =cut |
| 465 | | | | | |
| 466 | | | | | sub _common_config { |
| 467 | | | | | my $var = shift; |
| 468 | | | | | my $term = shift; |
| 469 | | | | | return if !defined($context->{$term}); |
| 470 | | | | | # Presumably $self->{$term} might be |
| 471 | | | | | # undefined if the config file given to &new |
| 472 | | | | | # didn't exist, and the caller didn't bother |
| 473 | | | | | # to check the return value. |
| 474 | | | | | |
| 475 | | | | | # Return the value of the requested config variable |
| 476 | | | | | return $context->{$term}->{$var}; |
| 477 | | | | | } |
| 478 | | | | | |
| 479 | | | | | sub config { |
| 480 | | | | | return _common_config($_[1],'config'); |
| 481 | | | | | } |
| 482 | | | | | sub zebraconfig { |
| 483 | | | | | return _common_config($_[1],'server'); |
| 484 | | | | | } |
| 485 | | | | | sub ModZebrations { |
| 486 | | | | | return _common_config($_[1],'serverinfo'); |
| 487 | | | | | } |
| 488 | | | | | |
| 489 | | | | | =head2 preference |
| 490 | | | | | |
| 491 | | | | | $sys_preference = C4::Context->preference('some_variable'); |
| 492 | | | | | |
| 493 | | | | | Looks up the value of the given system preference in the |
| 494 | | | | | systempreferences table of the Koha database, and returns it. If the |
| 495 | | | | | variable is not set or does not exist, undef is returned. |
| 496 | | | | | |
| 497 | | | | | In case of an error, this may return 0. |
| 498 | | | | | |
| 499 | | | | | Note: It is impossible to tell the difference between system |
| 500 | | | | | preferences which do not exist, and those whose values are set to NULL |
| 501 | | | | | with this method. |
| 502 | | | | | |
| 503 | | | | | =cut |
| 504 | | | | | |
| 505 | | | | | # FIXME: running this under mod_perl will require a means of |
| 506 | | | | | # flushing the caching mechanism. |
| 507 | | | | | |
| 508 | | | | | my %sysprefs; |
| 509 | | | | | my $use_syspref_cache = 1; |
| 510 | | | | | |
| 511 | | | | | sub preference { |
| 512 | | | | | my $self = shift; |
| 513 | | | | | my $var = shift; # The system preference to return |
| 514 | | | | | |
| 515 | | | | | if ($use_syspref_cache && exists $sysprefs{lc $var}) { |
| 516 | | | | | return $sysprefs{lc $var}; |
| 517 | | | | | } |
| 518 | | | | | |
| 519 | | | | | my $dbh = C4::Context->dbh or return 0; |
| 520 | | | | | |
| 521 | | | | | my $value; |
| 522 | | | | | if ( defined $ENV{"OVERRIDE_SYSPREF_$var"} ) { |
| 523 | | | | | $value = $ENV{"OVERRIDE_SYSPREF_$var"}; |
| 524 | | | | | } else { |
| 525 | | | | | my $syspref; |
| 526 | | | | | eval { $syspref = Koha::Config::SysPrefs->find( lc $var ) }; |
| 527 | | | | | $value = $syspref ? $syspref->value() : undef; |
| 528 | | | | | } |
| 529 | | | | | |
| 530 | | | | | $sysprefs{lc $var} = $value; |
| 531 | | | | | return $value; |
| 532 | | | | | } |
| 533 | | | | | |
| 534 | | | | | sub boolean_preference { |
| 535 | | | | | my $self = shift; |
| 536 | | | | | my $var = shift; # The system preference to return |
| 537 | | | | | my $it = preference($self, $var); |
| 538 | | | | | return defined($it)? C4::Boolean::true_p($it): undef; |
| 539 | | | | | } |
| 540 | | | | | |
| 541 | | | | | =head2 enable_syspref_cache |
| 542 | | | | | |
| 543 | | | | | C4::Context->enable_syspref_cache(); |
| 544 | | | | | |
| 545 | | | | | Enable the in-memory syspref cache used by C4::Context. This is the |
| 546 | | | | | default behavior. |
| 547 | | | | | |
| 548 | | | | | =cut |
| 549 | | | | | |
| 550 | | | | | sub enable_syspref_cache { |
| 551 | | | | | my ($self) = @_; |
| 552 | | | | | $use_syspref_cache = 1; |
| 553 | | | | | } |
| 554 | | | | | |
| 555 | | | | | =head2 disable_syspref_cache |
| 556 | | | | | |
| 557 | | | | | C4::Context->disable_syspref_cache(); |
| 558 | | | | | |
| 559 | | | | | Disable the in-memory syspref cache used by C4::Context. This should be |
| 560 | | | | | used with Plack and other persistent environments. |
| 561 | | | | | |
| 562 | | | | | =cut |
| 563 | | | | | |
| 564 | | | | | sub disable_syspref_cache { |
| 565 | | | | | my ($self) = @_; |
| 566 | | | | | $use_syspref_cache = 0; |
| 567 | | | | | $self->clear_syspref_cache(); |
| 568 | | | | | } |
| 569 | | | | | |
| 570 | | | | | =head2 clear_syspref_cache |
| 571 | | | | | |
| 572 | | | | | C4::Context->clear_syspref_cache(); |
| 573 | | | | | |
| 574 | | | | | cleans the internal cache of sysprefs. Please call this method if |
| 575 | | | | | you update the systempreferences table. Otherwise, your new changes |
| 576 | | | | | will not be seen by this process. |
| 577 | | | | | |
| 578 | | | | | =cut |
| 579 | | | | | |
| 580 | | | | | sub clear_syspref_cache { |
| 581 | | | | | %sysprefs = (); |
| 582 | | | | | } |
| 583 | | | | | |
| 584 | | | | | =head2 set_preference |
| 585 | | | | | |
| 586 | | | | | C4::Context->set_preference( $variable, $value ); |
| 587 | | | | | |
| 588 | | | | | This updates a preference's value both in the systempreferences table and in |
| 589 | | | | | the sysprefs cache. |
| 590 | | | | | |
| 591 | | | | | =cut |
| 592 | | | | | |
| 593 | | | | | sub set_preference { |
| 594 | | | | | my $self = shift; |
| 595 | | | | | my $var = lc(shift); |
| 596 | | | | | my $value = shift; |
| 597 | | | | | |
| 598 | | | | | my $syspref = Koha::Config::SysPrefs->find( $var ); |
| 599 | | | | | my $type = $syspref ? $syspref->type() : undef; |
| 600 | | | | | |
| 601 | | | | | $value = 0 if ( $type && $type eq 'YesNo' && $value eq '' ); |
| 602 | | | | | |
| 603 | | | | | # force explicit protocol on OPACBaseURL |
| 604 | | | | | if ($var eq 'opacbaseurl' && substr($value,0,4) !~ /http/) { |
| 605 | | | | | $value = 'http://' . $value; |
| 606 | | | | | } |
| 607 | | | | | |
| 608 | | | | | if ($syspref) { |
| 609 | | | | | $syspref = $syspref->set( { value => $value } )->store(); |
| 610 | | | | | } |
| 611 | | | | | else { |
| 612 | | | | | $syspref = Koha::Config::SysPref->new( { variable => $var, value => $value } )->store(); |
| 613 | | | | | } |
| 614 | | | | | |
| 615 | | | | | if ($syspref) { |
| 616 | | | | | $sysprefs{$var} = $value; |
| 617 | | | | | } |
| 618 | | | | | } |
| 619 | | | | | |
| 620 | | | | | =head2 Zconn |
| 621 | | | | | |
| 622 | | | | | $Zconn = C4::Context->Zconn |
| 623 | | | | | |
| 624 | | | | | Returns a connection to the Zebra database |
| 625 | | | | | |
| 626 | | | | | C<$self> |
| 627 | | | | | |
| 628 | | | | | C<$server> one of the servers defined in the koha-conf.xml file |
| 629 | | | | | |
| 630 | | | | | C<$async> whether this is a asynchronous connection |
| 631 | | | | | |
| 632 | | | | | =cut |
| 633 | | | | | |
| 634 | | | | | sub Zconn { |
| 635 | | | | | my ($self, $server, $async ) = @_; |
| 636 | | | | | my $cache_key = join ('::', (map { $_ // '' } ($server, $async ))); |
| 637 | | | | | if ( (!defined($ENV{GATEWAY_INTERFACE})) && defined($context->{"Zconn"}->{$cache_key}) && (0 == $context->{"Zconn"}->{$cache_key}->errcode()) ) { |
| 638 | | | | | # if we are running the script from the commandline, lets try to use the caching |
| 639 | | | | | return $context->{"Zconn"}->{$cache_key}; |
| 640 | | | | | } |
| 641 | | | | | $context->{"Zconn"}->{$cache_key}->destroy() if defined($context->{"Zconn"}->{$cache_key}); #destroy old connection before making a new one |
| 642 | | | | | $context->{"Zconn"}->{$cache_key} = &_new_Zconn( $server, $async ); |
| 643 | | | | | return $context->{"Zconn"}->{$cache_key}; |
| 644 | | | | | } |
| 645 | | | | | |
| 646 | | | | | =head2 _new_Zconn |
| 647 | | | | | |
| 648 | | | | | $context->{"Zconn"} = &_new_Zconn($server,$async); |
| 649 | | | | | |
| 650 | | | | | Internal function. Creates a new database connection from the data given in the current context and returns it. |
| 651 | | | | | |
| 652 | | | | | C<$server> one of the servers defined in the koha-conf.xml file |
| 653 | | | | | |
| 654 | | | | | C<$async> whether this is a asynchronous connection |
| 655 | | | | | |
| 656 | | | | | C<$auth> whether this connection has rw access (1) or just r access (0 or NULL) |
| 657 | | | | | |
| 658 | | | | | =cut |
| 659 | | | | | |
| 660 | | | | | sub _new_Zconn { |
| 661 | | | | | my ( $server, $async ) = @_; |
| 662 | | | | | |
| 663 | | | | | my $tried=0; # first attempt |
| 664 | | | | | my $Zconn; # connection object |
| 665 | | | | | my $elementSetName; |
| 666 | | | | | my $index_mode; |
| 667 | | | | | my $syntax; |
| 668 | | | | | |
| 669 | | | | | $server //= "biblioserver"; |
| 670 | | | | | |
| 671 | | | | | if ( $server eq 'biblioserver' ) { |
| 672 | | | | | $index_mode = $context->{'config'}->{'zebra_bib_index_mode'} // 'dom'; |
| 673 | | | | | } elsif ( $server eq 'authorityserver' ) { |
| 674 | | | | | $index_mode = $context->{'config'}->{'zebra_auth_index_mode'} // 'dom'; |
| 675 | | | | | } |
| 676 | | | | | |
| 677 | | | | | if ( $index_mode eq 'grs1' ) { |
| 678 | | | | | $elementSetName = 'F'; |
| 679 | | | | | $syntax = ( $context->preference("marcflavour") eq 'UNIMARC' ) |
| 680 | | | | | ? 'unimarc' |
| 681 | | | | | : 'usmarc'; |
| 682 | | | | | |
| 683 | | | | | } else { # $index_mode eq 'dom' |
| 684 | | | | | $syntax = 'xml'; |
| 685 | | | | | $elementSetName = 'marcxml'; |
| 686 | | | | | } |
| 687 | | | | | |
| 688 | | | | | my $host = $context->{'listen'}->{$server}->{'content'}; |
| 689 | | | | | my $user = $context->{"serverinfo"}->{$server}->{"user"}; |
| 690 | | | | | my $password = $context->{"serverinfo"}->{$server}->{"password"}; |
| 691 | | | | | eval { |
| 692 | | | | | # set options |
| 693 | | | | | my $o = new ZOOM::Options(); |
| 694 | | | | | $o->option(user => $user) if $user && $password; |
| 695 | | | | | $o->option(password => $password) if $user && $password; |
| 696 | | | | | $o->option(async => 1) if $async; |
| 697 | | | | | $o->option(cqlfile=> $context->{"server"}->{$server}->{"cql2rpn"}); |
| 698 | | | | | $o->option(cclfile=> $context->{"serverinfo"}->{$server}->{"ccl2rpn"}); |
| 699 | | | | | $o->option(preferredRecordSyntax => $syntax); |
| 700 | | | | | $o->option(elementSetName => $elementSetName) if $elementSetName; |
| 701 | | | | | $o->option(databaseName => $context->{"config"}->{$server}||"biblios"); |
| 702 | | | | | |
| 703 | | | | | # create a new connection object |
| 704 | | | | | $Zconn= create ZOOM::Connection($o); |
| 705 | | | | | |
| 706 | | | | | # forge to server |
| 707 | | | | | $Zconn->connect($host, 0); |
| 708 | | | | | |
| 709 | | | | | # check for errors and warn |
| 710 | | | | | if ($Zconn->errcode() !=0) { |
| 711 | | | | | warn "something wrong with the connection: ". $Zconn->errmsg(); |
| 712 | | | | | } |
| 713 | | | | | }; |
| 714 | | | | | return $Zconn; |
| 715 | | | | | } |
| 716 | | | | | |
| 717 | | | | | # _new_dbh |
| 718 | | | | | # Internal helper function (not a method!). This creates a new |
| 719 | | | | | # database connection from the data given in the current context, and |
| 720 | | | | | # returns it. |
| 721 | | | | | sub _new_dbh |
| 722 | | | | | { |
| 723 | | | | | |
| 724 | | | | | Koha::Database->schema({ new => 1 })->storage->dbh; |
| 725 | | | | | } |
| 726 | | | | | |
| 727 | | | | | =head2 dbh |
| 728 | | | | | |
| 729 | | | | | $dbh = C4::Context->dbh; |
| 730 | | | | | |
| 731 | | | | | Returns a database handle connected to the Koha database for the |
| 732 | | | | | current context. If no connection has yet been made, this method |
| 733 | | | | | creates one, and connects to the database. |
| 734 | | | | | |
| 735 | | | | | This database handle is cached for future use: if you call |
| 736 | | | | | C<C4::Context-E<gt>dbh> twice, you will get the same handle both |
| 737 | | | | | times. If you need a second database handle, use C<&new_dbh> and |
| 738 | | | | | possibly C<&set_dbh>. |
| 739 | | | | | |
| 740 | | | | | =cut |
| 741 | | | | | |
| 742 | | | | | #' |
| 743 | | | | | sub dbh |
| 744 | | | | | { |
| 745 | | | | | my $self = shift; |
| 746 | | | | | my $params = shift; |
| 747 | | | | | my $sth; |
| 748 | | | | | |
| 749 | 1 | 2.77ms | | | unless ( $params->{new} ) { |
| 750 | | | | | return Koha::Database->schema->storage->dbh; |
| 751 | | | | | } |
| 752 | | | | | |
| 753 | | | | | return Koha::Database->schema({ new => 1 })->storage->dbh; |
| 754 | | | | | } |
| 755 | | | | | |
| 756 | | | | | =head2 new_dbh |
| 757 | | | | | |
| 758 | | | | | $dbh = C4::Context->new_dbh; |
| 759 | | | | | |
| 760 | | | | | Creates a new connection to the Koha database for the current context, |
| 761 | | | | | and returns the database handle (a C<DBI::db> object). |
| 762 | | | | | |
| 763 | | | | | The handle is not saved anywhere: this method is strictly a |
| 764 | | | | | convenience function; the point is that it knows which database to |
| 765 | | | | | connect to so that the caller doesn't have to know. |
| 766 | | | | | |
| 767 | | | | | =cut |
| 768 | | | | | |
| 769 | | | | | #' |
| 770 | | | | | sub new_dbh |
| 771 | | | | | { |
| 772 | | | | | my $self = shift; |
| 773 | | | | | |
| 774 | | | | | return &dbh({ new => 1 }); |
| 775 | | | | | } |
| 776 | | | | | |
| 777 | | | | | =head2 set_dbh |
| 778 | | | | | |
| 779 | | | | | $my_dbh = C4::Connect->new_dbh; |
| 780 | | | | | C4::Connect->set_dbh($my_dbh); |
| 781 | | | | | ... |
| 782 | | | | | C4::Connect->restore_dbh; |
| 783 | | | | | |
| 784 | | | | | C<&set_dbh> and C<&restore_dbh> work in a manner analogous to |
| 785 | | | | | C<&set_context> and C<&restore_context>. |
| 786 | | | | | |
| 787 | | | | | C<&set_dbh> saves the current database handle on a stack, then sets |
| 788 | | | | | the current database handle to C<$my_dbh>. |
| 789 | | | | | |
| 790 | | | | | C<$my_dbh> is assumed to be a good database handle. |
| 791 | | | | | |
| 792 | | | | | =cut |
| 793 | | | | | |
| 794 | | | | | #' |
| 795 | | | | | sub set_dbh |
| 796 | | | | | { |
| 797 | | | | | my $self = shift; |
| 798 | | | | | my $new_dbh = shift; |
| 799 | | | | | |
| 800 | | | | | # Save the current database handle on the handle stack. |
| 801 | | | | | # We assume that $new_dbh is all good: if the caller wants to |
| 802 | | | | | # screw himself by passing an invalid handle, that's fine by |
| 803 | | | | | # us. |
| 804 | | | | | push @{$context->{"dbh_stack"}}, $context->{"dbh"}; |
| 805 | | | | | $context->{"dbh"} = $new_dbh; |
| 806 | | | | | } |
| 807 | | | | | |
| 808 | | | | | =head2 restore_dbh |
| 809 | | | | | |
| 810 | | | | | C4::Context->restore_dbh; |
| 811 | | | | | |
| 812 | | | | | Restores the database handle saved by an earlier call to |
| 813 | | | | | C<C4::Context-E<gt>set_dbh>. |
| 814 | | | | | |
| 815 | | | | | =cut |
| 816 | | | | | |
| 817 | | | | | #' |
| 818 | | | | | sub restore_dbh |
| 819 | | | | | { |
| 820 | | | | | my $self = shift; |
| 821 | | | | | |
| 822 | | | | | if ($#{$context->{"dbh_stack"}} < 0) |
| 823 | | | | | { |
| 824 | | | | | # Stack underflow |
| 825 | | | | | die "DBH stack underflow"; |
| 826 | | | | | } |
| 827 | | | | | |
| 828 | | | | | # Pop the old database handle and set it. |
| 829 | | | | | $context->{"dbh"} = pop @{$context->{"dbh_stack"}}; |
| 830 | | | | | |
| 831 | | | | | # FIXME - If it is determined that restore_context should |
| 832 | | | | | # return something, then this function should, too. |
| 833 | | | | | } |
| 834 | | | | | |
| 835 | | | | | =head2 queryparser |
| 836 | | | | | |
| 837 | | | | | $queryparser = C4::Context->queryparser |
| 838 | | | | | |
| 839 | | | | | Returns a handle to an initialized Koha::QueryParser::Driver::PQF object. |
| 840 | | | | | |
| 841 | | | | | =cut |
| 842 | | | | | |
| 843 | | | | | sub queryparser { |
| 844 | | | | | my $self = shift; |
| 845 | | | | | unless (defined $context->{"queryparser"}) { |
| 846 | | | | | $context->{"queryparser"} = &_new_queryparser(); |
| 847 | | | | | } |
| 848 | | | | | |
| 849 | | | | | return |
| 850 | | | | | defined( $context->{"queryparser"} ) |
| 851 | | | | | ? $context->{"queryparser"}->new |
| 852 | | | | | : undef; |
| 853 | | | | | } |
| 854 | | | | | |
| 855 | | | | | =head2 _new_queryparser |
| 856 | | | | | |
| 857 | | | | | Internal helper function to create a new QueryParser object. QueryParser |
| 858 | | | | | is loaded dynamically so as to keep the lack of the QueryParser library from |
| 859 | | | | | getting in anyone's way. |
| 860 | | | | | |
| 861 | | | | | =cut |
| 862 | | | | | |
| 863 | | | | | sub _new_queryparser { |
| 864 | | | | | my $qpmodules = { |
| 865 | | | | | 'OpenILS::QueryParser' => undef, |
| 866 | | | | | 'Koha::QueryParser::Driver::PQF' => undef |
| 867 | | | | | }; |
| 868 | | | | | if ( can_load( 'modules' => $qpmodules ) ) { |
| 869 | | | | | my $QParser = Koha::QueryParser::Driver::PQF->new(); |
| 870 | | | | | my $config_file = $context->config('queryparser_config'); |
| 871 | | | | | $config_file ||= '/etc/koha/searchengine/queryparser.yaml'; |
| 872 | | | | | if ( $QParser->load_config($config_file) ) { |
| 873 | | | | | # Set 'keyword' as the default search class |
| 874 | | | | | $QParser->default_search_class('keyword'); |
| 875 | | | | | # TODO: allow indexes to be configured in the database |
| 876 | | | | | return $QParser; |
| 877 | | | | | } |
| 878 | | | | | } |
| 879 | | | | | return; |
| 880 | | | | | } |
| 881 | | | | | |
| 882 | | | | | =head2 marcfromkohafield |
| 883 | | | | | |
| 884 | | | | | $dbh = C4::Context->marcfromkohafield; |
| 885 | | | | | |
| 886 | | | | | Returns a hash with marcfromkohafield. |
| 887 | | | | | |
| 888 | | | | | This hash is cached for future use: if you call |
| 889 | | | | | C<C4::Context-E<gt>marcfromkohafield> twice, you will get the same hash without real DB access |
| 890 | | | | | |
| 891 | | | | | =cut |
| 892 | | | | | |
| 893 | | | | | #' |
| 894 | | | | | sub marcfromkohafield |
| 895 | | | | | { |
| 896 | | | | | my $retval = {}; |
| 897 | | | | | |
| 898 | | | | | # If the hash already exists, return it. |
| 899 | | | | | return $context->{"marcfromkohafield"} if defined($context->{"marcfromkohafield"}); |
| 900 | | | | | |
| 901 | | | | | # No hash. Create one. |
| 902 | | | | | $context->{"marcfromkohafield"} = &_new_marcfromkohafield(); |
| 903 | | | | | |
| 904 | | | | | return $context->{"marcfromkohafield"}; |
| 905 | | | | | } |
| 906 | | | | | |
| 907 | | | | | # _new_marcfromkohafield |
| 908 | | | | | sub _new_marcfromkohafield |
| 909 | | | | | { |
| 910 | | | | | my $dbh = C4::Context->dbh; |
| 911 | | | | | my $marcfromkohafield; |
| 912 | | | | | my $sth = $dbh->prepare("select frameworkcode,kohafield,tagfield,tagsubfield from marc_subfield_structure where kohafield > ''"); |
| 913 | | | | | $sth->execute; |
| 914 | | | | | while (my ($frameworkcode,$kohafield,$tagfield,$tagsubfield) = $sth->fetchrow) { |
| 915 | | | | | my $retval = {}; |
| 916 | | | | | $marcfromkohafield->{$frameworkcode}->{$kohafield} = [$tagfield,$tagsubfield]; |
| 917 | | | | | } |
| 918 | | | | | return $marcfromkohafield; |
| 919 | | | | | } |
| 920 | | | | | |
| 921 | | | | | =head2 userenv |
| 922 | | | | | |
| 923 | | | | | C4::Context->userenv; |
| 924 | | | | | |
| 925 | | | | | Retrieves a hash for user environment variables. |
| 926 | | | | | |
| 927 | | | | | This hash shall be cached for future use: if you call |
| 928 | | | | | C<C4::Context-E<gt>userenv> twice, you will get the same hash without real DB access |
| 929 | | | | | |
| 930 | | | | | =cut |
| 931 | | | | | |
| 932 | | | | | #' |
| 933 | | | | | sub userenv { |
| 934 | | | | | my $var = $context->{"activeuser"}; |
| 935 | | | | | if (defined $var and defined $context->{"userenv"}->{$var}) { |
| 936 | | | | | return $context->{"userenv"}->{$var}; |
| 937 | | | | | } else { |
| 938 | | | | | return; |
| 939 | | | | | } |
| 940 | | | | | } |
| 941 | | | | | |
| 942 | | | | | =head2 set_userenv |
| 943 | | | | | |
| 944 | | | | | C4::Context->set_userenv($usernum, $userid, $usercnum, |
| 945 | | | | | $userfirstname, $usersurname, |
| 946 | | | | | $userbranch, $branchname, $userflags, |
| 947 | | | | | $emailaddress, $branchprinter, $persona); |
| 948 | | | | | |
| 949 | | | | | Establish a hash of user environment variables. |
| 950 | | | | | |
| 951 | | | | | set_userenv is called in Auth.pm |
| 952 | | | | | |
| 953 | | | | | =cut |
| 954 | | | | | |
| 955 | | | | | #' |
| 956 | | | | | sub set_userenv { |
| 957 | | | | | shift @_; |
| 958 | | | | | my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter, $persona, $shibboleth)= |
| 959 | | | | | map { Encode::is_utf8( $_ ) ? $_ : Encode::decode('UTF-8', $_) } # CGI::Session doesn't handle utf-8, so we decode it here |
| 960 | | | | | @_; |
| 961 | | | | | my $var=$context->{"activeuser"} || ''; |
| 962 | | | | | my $cell = { |
| 963 | | | | | "number" => $usernum, |
| 964 | | | | | "id" => $userid, |
| 965 | | | | | "cardnumber" => $usercnum, |
| 966 | | | | | "firstname" => $userfirstname, |
| 967 | | | | | "surname" => $usersurname, |
| 968 | | | | | #possibly a law problem |
| 969 | | | | | "branch" => $userbranch, |
| 970 | | | | | "branchname" => $branchname, |
| 971 | | | | | "flags" => $userflags, |
| 972 | | | | | "emailaddress" => $emailaddress, |
| 973 | | | | | "branchprinter" => $branchprinter, |
| 974 | | | | | "persona" => $persona, |
| 975 | | | | | "shibboleth" => $shibboleth, |
| 976 | | | | | }; |
| 977 | | | | | $context->{userenv}->{$var} = $cell; |
| 978 | | | | | return $cell; |
| 979 | | | | | } |
| 980 | | | | | |
| 981 | | | | | sub set_shelves_userenv { |
| 982 | | | | | my ($type, $shelves) = @_ or return; |
| 983 | | | | | my $activeuser = $context->{activeuser} or return; |
| 984 | | | | | $context->{userenv}->{$activeuser}->{barshelves} = $shelves if $type eq 'bar'; |
| 985 | | | | | $context->{userenv}->{$activeuser}->{pubshelves} = $shelves if $type eq 'pub'; |
| 986 | | | | | $context->{userenv}->{$activeuser}->{totshelves} = $shelves if $type eq 'tot'; |
| 987 | | | | | } |
| 988 | | | | | |
| 989 | | | | | sub get_shelves_userenv { |
| 990 | | | | | my $active; |
| 991 | | | | | unless ($active = $context->{userenv}->{$context->{activeuser}}) { |
| 992 | | | | | $debug and warn "get_shelves_userenv cannot retrieve context->{userenv}->{context->{activeuser}}"; |
| 993 | | | | | return; |
| 994 | | | | | } |
| 995 | | | | | my $totshelves = $active->{totshelves} or undef; |
| 996 | | | | | my $pubshelves = $active->{pubshelves} or undef; |
| 997 | | | | | my $barshelves = $active->{barshelves} or undef; |
| 998 | | | | | return ($totshelves, $pubshelves, $barshelves); |
| 999 | | | | | } |
| 1000 | | | | | |
| 1001 | | | | | =head2 _new_userenv |
| 1002 | | | | | |
| 1003 | | | | | C4::Context->_new_userenv($session); # FIXME: This calling style is wrong for what looks like an _internal function |
| 1004 | | | | | |
| 1005 | | | | | Builds a hash for user environment variables. |
| 1006 | | | | | |
| 1007 | | | | | This hash shall be cached for future use: if you call |
| 1008 | | | | | C<C4::Context-E<gt>userenv> twice, you will get the same hash without real DB access |
| 1009 | | | | | |
| 1010 | | | | | _new_userenv is called in Auth.pm |
| 1011 | | | | | |
| 1012 | | | | | =cut |
| 1013 | | | | | |
| 1014 | | | | | #' |
| 1015 | | | | | sub _new_userenv |
| 1016 | | | | | { |
| 1017 | | | | | shift; # Useless except it compensates for bad calling style |
| 1018 | | | | | my ($sessionID)= @_; |
| 1019 | | | | | $context->{"activeuser"}=$sessionID; |
| 1020 | | | | | } |
| 1021 | | | | | |
| 1022 | | | | | =head2 _unset_userenv |
| 1023 | | | | | |
| 1024 | | | | | C4::Context->_unset_userenv; |
| 1025 | | | | | |
| 1026 | | | | | Destroys the hash for activeuser user environment variables. |
| 1027 | | | | | |
| 1028 | | | | | =cut |
| 1029 | | | | | |
| 1030 | | | | | #' |
| 1031 | | | | | |
| 1032 | | | | | sub _unset_userenv |
| 1033 | | | | | { |
| 1034 | | | | | my ($sessionID)= @_; |
| 1035 | | | | | undef $context->{"activeuser"} if ($context->{"activeuser"} eq $sessionID); |
| 1036 | | | | | } |
| 1037 | | | | | |
| 1038 | | | | | |
| 1039 | | | | | =head2 get_versions |
| 1040 | | | | | |
| 1041 | | | | | C4::Context->get_versions |
| 1042 | | | | | |
| 1043 | | | | | Gets various version info, for core Koha packages, Currently called from carp handle_errors() sub, to send to browser if 'DebugLevel' syspref is set to '2'. |
| 1044 | | | | | |
| 1045 | | | | | =cut |
| 1046 | | | | | |
| 1047 | | | | | #' |
| 1048 | | | | | |
| 1049 | | | | | # A little example sub to show more debugging info for CGI::Carp |
| 1050 | | | | | sub get_versions { |
| 1051 | | | | | my %versions; |
| 1052 | | | | | $versions{kohaVersion} = Koha::version(); |
| 1053 | | | | | $versions{kohaDbVersion} = C4::Context->preference('version'); |
| 1054 | | | | | $versions{osVersion} = join(" ", POSIX::uname()); |
| 1055 | | | | | $versions{perlVersion} = $]; |
| 1056 | | | | | { |
| 1057 | | | | | no warnings qw(exec); # suppress warnings if unable to find a program in $PATH |
| 1058 | | | | | $versions{mysqlVersion} = `mysql -V`; |
| 1059 | | | | | $versions{apacheVersion} = `httpd -v`; |
| 1060 | | | | | $versions{apacheVersion} = `httpd2 -v` unless $versions{apacheVersion} ; |
| 1061 | | | | | $versions{apacheVersion} = `apache2 -v` unless $versions{apacheVersion} ; |
| 1062 | | | | | $versions{apacheVersion} = `/usr/sbin/apache2 -v` unless $versions{apacheVersion} ; |
| 1063 | | | | | } |
| 1064 | | | | | return %versions; |
| 1065 | | | | | } |
| 1066 | | | | | |
| 1067 | | | | | |
| 1068 | | | | | =head2 tz |
| 1069 | | | | | |
| 1070 | | | | | C4::Context->tz |
| 1071 | | | | | |
| 1072 | | | | | Returns a DateTime::TimeZone object for the system timezone |
| 1073 | | | | | |
| 1074 | | | | | =cut |
| 1075 | | | | | |
| 1076 | | | | | sub tz { |
| 1077 | | | | | my $self = shift; |
| 1078 | | | | | if (!defined $context->{tz}) { |
| 1079 | | | | | $context->{tz} = DateTime::TimeZone->new(name => 'local'); |
| 1080 | | | | | } |
| 1081 | | | | | return $context->{tz}; |
| 1082 | | | | | } |
| 1083 | | | | | |
| 1084 | | | | | |
| 1085 | | | | | =head2 IsSuperLibrarian |
| 1086 | | | | | |
| 1087 | | | | | C4::Context->IsSuperLibrarian(); |
| 1088 | | | | | |
| 1089 | | | | | =cut |
| 1090 | | | | | |
| 1091 | | | | | sub IsSuperLibrarian { |
| 1092 | | | | | my $userenv = C4::Context->userenv; |
| 1093 | | | | | |
| 1094 | | | | | unless ( $userenv and exists $userenv->{flags} ) { |
| 1095 | | | | | # If we reach this without a user environment, |
| 1096 | | | | | # assume that we're running from a command-line script, |
| 1097 | | | | | # and act as a superlibrarian. |
| 1098 | | | | | carp("C4::Context->userenv not defined!"); |
| 1099 | | | | | return 1; |
| 1100 | | | | | } |
| 1101 | | | | | |
| 1102 | | | | | return ($userenv->{flags}//0) % 2; |
| 1103 | | | | | } |
| 1104 | | | | | |
| 1105 | | | | | =head2 interface |
| 1106 | | | | | |
| 1107 | | | | | Sets the current interface for later retrieval in any Perl module |
| 1108 | | | | | |
| 1109 | | | | | C4::Context->interface('opac'); |
| 1110 | | | | | C4::Context->interface('intranet'); |
| 1111 | | | | | my $interface = C4::Context->interface; |
| 1112 | | | | | |
| 1113 | | | | | =cut |
| 1114 | | | | | |
| 1115 | | | | | sub interface { |
| 1116 | | | | | my ($class, $interface) = @_; |
| 1117 | | | | | |
| 1118 | | | | | if (defined $interface) { |
| 1119 | | | | | $interface = lc $interface; |
| 1120 | | | | | if ($interface eq 'opac' || $interface eq 'intranet') { |
| 1121 | | | | | $context->{interface} = $interface; |
| 1122 | | | | | } else { |
| 1123 | | | | | warn "invalid interface : '$interface'"; |
| 1124 | | | | | } |
| 1125 | | | | | } |
| 1126 | | | | | |
| 1127 | | | | | return $context->{interface} // 'opac'; |
| 1128 | | | | | } |
| 1129 | | | | | |
| 1130 | | | | | 1; |
| 1131 | | | | | __END__ |
| 1132 | | | | | |
| 1133 | | | | | =head1 ENVIRONMENT |
| 1134 | | | | | |
| 1135 | | | | | =head2 C<KOHA_CONF> |
| 1136 | | | | | |
| 1137 | | | | | Specifies the configuration file to read. |
| 1138 | | | | | |
| 1139 | | | | | =head1 SEE ALSO |
| 1140 | | | | | |
| 1141 | | | | | XML::Simple |
| 1142 | | | | | |
| 1143 | | | | | =head1 AUTHORS |
| 1144 | | | | | |
| 1145 | | | | | Andrew Arensburger <arensb at ooblick dot com> |
| 1146 | | | | | |
| 1147 | | | | | Joshua Ferraro <jmf at liblime dot com> |
| 1148 | | | | | |