Translation updates for Koha 19.05.02
[koha.git] / misc / admin / koha-preferences
1 #!/usr/bin/perl
2 #
3 # Copyright 2010 Jesse Weaver, Koha Dev Team
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19 #
20
21 use Koha::Script;
22 use C4::Boolean;
23 use C4::Context;
24 use C4::Debug;
25 use C4::Log;
26 use Getopt::Long;
27 use Pod::Usage;
28 use YAML::Syck qw();
29 $YAML::Syck::ImplicitTyping = 1;
30 $YAML::Syck::SortKeys = 1;
31 our %NOT_SET_PREFS = map { $_, 1 } qw( Version );
32
33 =head1 NAME
34
35 koha-preferences - Get, set, dump and load Koha system preferences
36
37 =head1 SYNOPSIS
38
39 misc/admin/koha-preferences COMMAND ...
40
41 =cut
42
43 sub print_usage {
44     my ( $annoyed ) = @_;
45
46     if ( $annoyed ) {
47         pod2usage( -verbose => 1, -exitval => 1, -output => \*STDERR );
48     } else {
49         pod2usage( -verbose => 1, -exitval => 0 );
50     }
51 }
52
53 sub _debug {
54     my ( $message ) = @_;
55
56     print STDERR $message . "\n" if ( $C4::Debug::debug );
57 }
58
59 sub _normalize_value {
60     my ($row) = @_;
61
62     # AFAIK, there are no sysprefs where NULL has a different meaning than ''.
63     return ( $row->{'value'} || '' ) unless ( $row->{'type'} eq 'YesNo' );
64
65     #
66     # In theory, YesNo sysprefs should always contain 1/0.
67     # In practice, however, they don't.
68     # - Yogi Berra
69     #
70     my $bool_value = eval {
71         return C4::Boolean::true_p( $row->{'value'} ) ? 1 : 0;
72     };
73     if ( $@ ) {
74         return 0;
75     } else {
76         return $bool_value;
77     }
78 }
79
80 sub _set_preference {
81     my ( $preference, $value ) = @_;
82
83     _debug( "Setting $preference to $value" );
84
85     C4::Context->set_preference( $preference, $value );
86 }
87
88 sub GetPreferences {
89     my $dbh = C4::Context->dbh;
90
91     return {
92         map { $_->{'variable'},  _normalize_value($_) }
93         @{ $dbh->selectall_arrayref( "
94             SELECT
95               variable, value, type
96               FROM systempreferences
97         ", { Slice => {} } ) }
98     };
99 }
100
101 sub SetPreferences {
102     my ( %preferences ) = @_;
103
104     my $dbh = C4::Context->dbh;
105
106     # First, a quick check to make sure all of the system preferences exist
107     my $current_state = $dbh->selectall_arrayref( "
108         SELECT
109           variable, type, value
110           FROM systempreferences
111           WHERE variable IN (" . join( ', ', map( "?", keys %preferences ) ) . ")
112     ", { Slice => {} }, keys %preferences );
113
114     exit 2 if ( scalar( @$current_state ) != scalar( keys %preferences ) );
115
116     foreach my $row ( @$current_state ) {
117         # YAML::Syck encodes no as '', so deal with that
118         $preferences{$row->{'variable'}} = $preferences{$row->{'variable'}} eq '' ? 0 : C4::Boolean::true_p( $preferences{$row->{'variable'}} ) if ( $row->{'type'} eq 'YesNo' );
119     }
120
121     # Iterate through again, now that we've checked all of the YesNo sysprefs
122
123     foreach my $row ( @$current_state ) {
124         next if ( $preferences{$row->{'variable'}} eq $row->{'value'} );
125
126         _set_preference( $row->{'variable'}, $preferences{$row->{'variable'}} );
127     }
128
129     # FIXME This may be not needed
130     C4::Context->clear_syspref_cache();
131 }
132
133 sub _fetch_preference {
134     my ( $preference ) = @_;
135
136     my $dbh = C4::Context->dbh;
137
138     my $row = $dbh->selectrow_hashref( "
139         SELECT
140           variable, value, type
141           FROM systempreferences
142           WHERE variable = ?
143           LIMIT 1
144     ", {}, $preference );
145
146     exit 2 unless ( $row );
147
148     return $row;
149 }
150
151 sub GetPreference {
152     my ( $preference ) = @_;
153
154     my $row = _fetch_preference( $preference );
155
156     return _normalize_value( $row );
157 }
158
159 sub SetPreference {
160     my ( $preference, $value ) = @_;
161
162     my $row = _fetch_preference( $preference );
163
164     $value = C4::Boolean::true_p($value) ? 1 : 0 if ( $row->{'type'} eq 'YesNo' );
165
166     exit 3 if ( $value eq $row->{'value'} );
167
168     _set_preference( $preference, $value );
169 }
170
171 sub ClearPreference {
172     my ( $preference ) = @_;
173
174     my $value = '';
175
176     my $row = _fetch_preference( $preference );
177
178     $value = 0 if ( $row->{'type'} eq 'YesNo' );
179
180     exit 3 if ( $value eq $row->{'value'} );
181
182     _set_preference( $preference, $value );
183 }
184
185 =head1 OPTIONS
186
187 COMMAND can be any of the following:
188
189 =over
190
191 =item B<dump> [ -o I<OUTFILE> ]
192
193 Dump all of Koha's system preferences as a simple YAML mapping into OUTFILE or
194 STDOUT.
195
196 =item B<load> [ -i I<INFILE> ] [ -f|--force ]
197
198 Reads system preferences specified in YAML in INFILE or STDIN.  Will exit with a
199 status of 2, without setting any sysprefs, if any of the sysprefs do not exist.
200 Will also exit if any of the sysprefs are YesNo and have an invalid value.
201
202 If there is a Version syspref in the input, it will not be set in the database,
203 but it will be checked to make sure the running Koha version is equal or higher.
204 The script will exit with a status of 4 if this is not true. Pass the -f option
205 to skip this check.
206
207 =item B<get> I<PREFERENCE>
208
209 Print the value of the system preference PREFERENCE, followed by a newline.  If
210 no such syspref exists, will exit with a status of 2.
211
212 =item B<set> I<PREFERENCE> I<VALUE>
213
214 Set the system preference PREFERENCE to the value VALUE. If no such syspref
215 exists, will exit with a status of 2. If the syspref already has that value,
216 will exit with a status of 3.
217
218 If the syspref is YesNo, will accept only a boolean value, but the syntax for
219 these is fairly lax (yes/no, on/off, 1/0, n/y, true/false are all accepted).
220
221 =item B<clear> I<PREFERENCE>
222
223 Clears the value of the system preference PREFERENCE. If no such syspref exists,
224 will exit with a status of 2. Will set YesNo sysprefs to 'false'.
225
226 =item B<manual>
227
228 Print a longer, more detailed manual.
229
230 =cut
231
232 my %commands = (
233     dump => sub{
234         my ( $outfile );
235
236         GetOptions(
237             'o:s' => \$outfile
238         ) || _print_usage( 1 );
239
240         if ( $outfile ) {
241             YAML::Syck::DumpFile( $outfile, GetPreferences() );
242         } else {
243             print YAML::Syck::Dump( GetPreferences() );
244         }
245     },
246     load => sub {
247         my ( $infile, $force_version );
248
249         GetOptions(
250             'i:s' => \$infile,
251             'f' => \$force_version,
252         );
253
254         my $preferences = YAML::Syck::LoadFile($infile || \*STDIN);
255
256         die "Expected a YAML mapping" if ( ref($preferences) ne 'HASH' );
257
258         die "Tried to load preferences for version " . $preferences->{'Version'} . ", we are " . C4::Context->preference( 'Version' ) if ( $preferences->{'Version'} && C4::Context->preference( 'Version' ) < $preferences->{'Version'} );
259
260         my %prefs_to_set = (
261             map { $_, $preferences->{$_} }
262             grep { !$NOT_SET_PREFS{$_} }
263             keys %$preferences
264         );
265
266         SetPreferences( %prefs_to_set );
267     },
268     get => sub {
269         my ( $preference ) = @_;
270
271         print_usage() unless ( $preference );
272
273         print GetPreference( $preference ) . "\n";
274     },
275     set => sub {
276         my ( $preference, $value ) = @_;
277
278         print_usage() unless ( $preference && defined($value) );
279
280         SetPreference( $preference, $value );
281     },
282     clear => sub {
283         my ( $preference ) = @_;
284
285         print_usage() unless ( $preference );
286
287         ClearPreference( $preference );
288     },
289     manual => sub {
290         pod2usage( -verbose => 2 );
291     }
292 );
293
294 print_usage() if ( $ARGV[0] =~ /^(-h|--help|-help|help)$/ );
295
296 print_usage( 1 ) if ( !$ARGV[0] || ref($commands{$ARGV[0]}) ne 'CODE' );
297
298 $command = $commands{$ARGV[0]};
299 shift @ARGV;
300 $command->(@ARGV);
301
302 =item B<help>
303
304 Print a short usage message.
305
306 =back
307
308 =head1 EXAMPLES
309
310   $ export KOHA_DEBUG=1 # Used here to show what is being stored
311   $ misc/admin/koha-preferences get viewISBD
312   0
313   $ misc/admin/koha-preferences set viewISBD on
314   Setting viewISBD to 1
315   $ misc/admin/koha-preferences dump -o preferences.yaml
316   $ [ edit preferences.yaml ]
317   $ misc/admin/koha-preferences load -i preferences.yaml
318   $ misc/admin/koha-preferences load -i preferences-too-new.yaml
319   Tried to load preferences for version 3.0500012, we are 3.0300009 at misc/admin/koha-preferences line 255
320   $ misc/admin/koha-preferences load # Can also work from STDIN
321   XISBN: false
322   viewMARC: y
323   [ Control-D ]
324   Setting viewMARC to 1
325   Setting XISBN to 0
326
327 =cut