replace syslog with warns
[koha.git] / C4 / Labels / Layout.pm
1 package C4::Labels::Layout;
2
3 use strict;
4 use warnings;
5
6 use DBI qw(neat);
7
8 use C4::Context;
9 use C4::Debug;
10 use C4::Labels::PDF;
11
12 BEGIN {
13     use version; our $VERSION = qv('1.0.0_1');
14 }
15
16 # FIXME: Consider this style parameter verification instead...
17 #  my %param = @_;
18 #   for (keys %param)
19 #    {   my $lc = lc($_); 
20 #        if (exists $default{$lc})
21 #        {  $default{$lc} = $param{$_}; 
22 #        }
23 #        else
24 #        {  print STDERR "Unknown parameter $_ , not used \n";
25 #        }
26 #    }
27
28 sub _check_params {
29     my $exit_code = 0;
30     my @valtmpl_id_params = (
31         'barcode_type',
32         'printing_type',
33         'layout_name',
34         'guidebox',
35         'font',
36         'font_size',
37         'callnum_split',
38         'text_justify',
39         'format_string',
40     );
41     if (scalar(@_) >1) {
42         my %given_params = @_;
43         foreach my $key (keys %given_params) {
44             if (!(grep m/$key/, @valtmpl_id_params)) {
45                 warn sprintf('(Multiple parameters) Unrecognized parameter type of "%s".', $key);
46                 $exit_code = 1;
47             }
48         }
49     }
50     else {
51         if (!(grep m/$_/, @valtmpl_id_params)) {
52             warn sprintf('(Single parameter) Unrecognized parameter type of "%s".', $_);
53             $exit_code = 1;
54         }
55     }
56     return $exit_code;
57 }
58
59 sub new {
60     my $invocant = shift;
61     if (_check_params(@_) eq 1) {
62         return -1;
63     }
64     my $type = ref($invocant) || $invocant;
65     my $self = {
66         barcode_type    =>      'CODE39',
67         printing_type   =>      'BAR',
68         layout_name     =>      'DEFAULT',
69         guidebox        =>      0,
70         font            =>      'TR',
71         font_size       =>      3,
72         callnum_split   =>      0,
73         text_justify    =>      'L',
74         format_string   =>      'title, author, isbn, issn, itemtype, barcode, callnumber',
75         @_,
76     };
77     bless ($self, $type);
78     return $self;
79 }
80
81 sub retrieve {
82     my $invocant = shift;
83     my %opts = @_;
84     my $type = ref($invocant) || $invocant;
85     my $query = "SELECT * FROM labels_layouts WHERE layout_id = ?";  
86     my $sth = C4::Context->dbh->prepare($query);
87     $sth->execute($opts{'layout_id'});
88     if ($sth->err) {
89         warn sprintf('Database returned the following error: %s', $sth->errstr);
90         return -1;
91     }
92     my $self = $sth->fetchrow_hashref;
93     bless ($self, $type);
94     return $self;
95 }
96
97 sub delete {
98     my $self = {};
99     my %opts = ();
100     my $call_type = '';
101     my $query_param = '';
102     if (ref($_[0])) {
103         $self = shift;  # check to see if this is a method call
104         $call_type = 'C4::Labels::Layout->delete';
105         $query_param = $self->{'layout_id'};
106     }
107     else {
108         %opts = @_;
109         $call_type = 'C4::Labels::Layout::delete';
110         $query_param = $opts{'layout_id'};
111     }
112     if ($query_param eq '') {   # If there is no layout id then we cannot delete it
113         warn sprintf('%s : Cannot delete layout as the layout id is invalid or non-existant.', $call_type);
114         return -1;
115     }
116     my $query = "DELETE FROM labels_layouts WHERE layout_id = ?";  
117     my $sth = C4::Context->dbh->prepare($query);
118     $sth->execute($query_param);
119     if ($sth->err) {
120         warn sprintf('%s : Database returned the following error: %s', $call_type, $sth->errstr);
121         return -1;
122     }
123     return 0;
124 }
125
126 sub save {
127     my $self = shift;
128     if ($self->{'layout_id'}) {        # if we have an id, the record exists and needs UPDATE
129         my @params;
130         my $query = "UPDATE labels_layouts SET ";
131         foreach my $key (keys %{$self}) {
132             next if $key eq 'layout_id';
133             push (@params, $self->{$key});
134             $query .= "$key=?, ";
135         }
136         $query = substr($query, 0, (length($query)-2));
137         $query .= " WHERE layout_id=?;";
138         push (@params, $self->{'layout_id'});
139         my $sth = C4::Context->dbh->prepare($query);
140         #local $sth->{TraceLevel} = "3";        # enable DBI trace and set level; outputs to STDERR
141         $sth->execute(@params);
142         if ($sth->err) {
143             warn sprintf('Database returned the following error: %s', $sth->errstr);
144             return -1;
145         }
146         return $self->{'layout_id'};
147     }
148     else {                      # otherwise create a new record
149         my @params;
150         my $query = "INSERT INTO labels_layouts (";
151         foreach my $key (keys %{$self}) {
152             push (@params, $self->{$key});
153             $query .= "$key, ";
154         }
155         $query = substr($query, 0, (length($query)-2));
156         $query .= ") VALUES (";
157         for (my $i=1; $i<=(scalar keys %$self); $i++) {
158             $query .= "?,";
159         }
160         $query = substr($query, 0, (length($query)-1));
161         $query .= ");";
162         my $sth = C4::Context->dbh->prepare($query);
163         $sth->execute(@params);
164         if ($sth->err) {
165             warn sprintf('Database returned the following error: %s', $sth->errstr);
166             return -1;
167         }
168         my $sth1 = C4::Context->dbh->prepare("SELECT MAX(layout_id) FROM labels_layouts;");
169         $sth1->execute();
170         my $id = $sth1->fetchrow_array;
171         return $id;
172     }
173 }
174
175 sub get_attr {
176     my $self = shift;
177     if (_check_params(@_) eq 1) {
178         return -1;
179     }
180     my ($attr) = @_;
181     if (exists($self->{$attr})) {
182         return $self->{$attr};
183     }
184     else {
185         return -1;
186     }
187     return;
188 }
189
190 sub set_attr {
191     my $self = shift;
192     if (_check_params(@_) eq 1) {
193         return -1;
194     }
195     my %attrs = @_;
196     foreach my $attrib (keys(%attrs)) {
197         $self->{$attrib} = $attrs{$attrib};
198     };
199     return 0;
200 }
201
202 sub get_text_wrap_cols {
203     my $self = shift;
204     my %params = @_;
205     my $string = '';
206     my $strwidth = 0;
207     my $col_count = 0;
208     my $textlimit = $params{'label_width'} - ( 3 * $params{'left_text_margin'});
209
210     while ($strwidth < $textlimit) {
211         $string .= '0';
212         $col_count++;
213         $strwidth = C4::Labels::PDF->StrWidth( $string, $self->{'font'}, $self->{'font_size'} );
214     }
215     return $col_count;
216 }
217
218 1;
219 __END__
220
221 =head1 NAME
222
223 C4::Labels::Layout -A class for creating and manipulating layout objects in Koha
224
225 =head1 ABSTRACT
226
227 This module provides methods for creating, retrieving, and otherwise manipulating label layout objects used by Koha to create and export labels.
228
229 =head1 METHODS
230
231 =head2 new()
232
233     Invoking the I<new> method constructs a new layout object containing the default values for a layout.
234     The following parameters are optionally accepted as key => value pairs:
235
236         C<barcode_type>         Defines the barcode type to be used on labels. NOTE: At present only the following barcode types are supported in the label creator code:
237
238 =over 9
239
240 =item .
241             CODE39          = Code 3 of 9
242
243 =item .
244             CODE39MOD       = Code 3 of 9 with modulo 43 checksum
245
246 =item .
247             CODE39MOD10     = Code 3 of 9 with modulo 10 checksum
248
249 =item .
250             COOP2OF5        = A varient of 2 of 5 barcode based on NEC's "Process 8000" code
251
252 =item .
253             INDUSTRIAL2OF5  = The standard 2 of 5 barcode (a binary level bar code developed by Identicon Corp. and Computer Identics Corp. in 1970)
254
255 =back
256
257         C<printing_type>        Defines the general layout to be used on labels. NOTE: At present there are only five printing types supported in the label creator code:
258
259 =over 9
260
261 =item .
262 BIB     = Only the bibliographic data is printed
263
264 =item .
265 BARBIB  = Barcode proceeds bibliographic data
266
267 =item .
268 BIBBAR  = Bibliographic data proceeds barcode
269
270 =item .
271 ALT     = Barcode and bibliographic data are printed on alternating labels
272
273 =item .
274 BAR     = Only the barcode is printed
275
276 =back
277
278         C<layout_name>          The descriptive name for this layout.
279         C<guidebox>             Setting this to '1' will result in a guide box being drawn around the labels marking the edge of each label
280         C<font>                 Defines the type of font to be used on labels. NOTE: The following fonts are available by default on most systems:
281
282 =over 9
283
284 =item .
285 TR      = Times-Roman
286
287 =item .
288 TB      = Times Bold
289
290 =item .
291 TI      = Times Italic
292
293 =item .
294 TBI     = Times Bold Italic
295
296 =item .
297 C       = Courier
298
299 =item .
300 CB      = Courier Bold
301
302 =item .
303 CO      = Courier Oblique (Italic)
304
305 =item .
306 CBO     = Courier Bold Oblique
307
308 =item .
309 H       = Helvetica
310
311 =item .
312 HB      = Helvetica Bold
313
314 =item .
315 HBO     = Helvetical Bold Oblique
316
317 =back
318
319         C<font_size>            Defines the size of the font in postscript points to be used on labels
320         C<callnum_split>        Setting this to '1' will enable call number splitting on labels
321         C<text_justify>         Defines the text justification to be used on labels. NOTE: The following justification styles are currently supported by label creator code:
322
323 =over 9
324
325 =item .
326 L       = Left
327
328 =item .
329 C       = Center
330
331 =item .
332 R       = Right
333
334 =back
335
336         C<format_string>        Defines what fields will be printed and in what order they will be printed on labels. These include any of the data fields that may be mapped
337                                 to your MARC frameworks. Specify MARC subfields as a 4-character tag-subfield string: ie. 254a Enclose a whitespace-separated list of fields
338                                 to concatenate on one line in double quotes. ie. "099a 099b" or "itemcallnumber barcode" Static text strings may be entered in single-quotes:
339                                 ie. 'Some static text here.'
340
341     example:
342         C<my $layout = Layout->new(); # Creates and returns a new layout object>
343
344         C<my $layout = C4::Labels::Layout->new(barcode_type => 'CODE39', printing_type => 'BIBBAR', font => 'C', font_size => 6); # Creates and returns a new layout object using
345             the supplied values to override the defaults>
346
347     B<NOTE:> This layout is I<not> written to the database until save() is invoked. You have been warned!
348
349 =head2 retrieve(layout_id => layout_id)
350
351     Invoking the I<retrieve> method constructs a new layout object containing the current values for layout_id. The method returns a new object upon success and 1 upon failure.
352     Errors are logged to the Apache log.
353
354     example:
355         C<my $layout = Layout->retrieve(layout_id => 1); # Retrieves layout record 1 and returns an object containing the record>
356
357 =head2 delete()
358
359     Invoking the delete method attempts to delete the layout from the database. The method returns 0 upon success and -1 upon failure. Errors are logged to the Apache log.
360     NOTE: This method may also be called as a function and passed a key/value pair simply deleteing that template from the database. See the example below.
361
362     examples:
363         C<my $exitstat = $layout->delete(); # to delete the record behind the $layout object>
364         C<my $exitstat = Layout->delete(layout_id => 1); # to delete layout record 1>
365
366 =head2 save()
367
368     Invoking the I<save> method attempts to insert the layout into the database if the layout is new and update the existing layout record if the layout exists.
369     The method returns the new record id upon success and -1 upon failure (This avoids conflicting with a record id of 1). Errors are logged to the Apache log.
370
371     example:
372         C<my $exitstat = $layout->save(); # to save the record behind the $layout object>
373
374 =head2 get_attr($attribute)
375
376     Invoking the I<get_attr> method will return the value of the requested attribute or -1 on errors.
377
378     example:
379         C<my $value = $layout->get_attr($attribute);>
380
381 =head2 set_attr(attribute => value, attribute_2 => value)
382
383     Invoking the I<set_attr> method will set the value of the supplied attributes to the supplied values. The method accepts key/value pairs separated by
384     commas.
385
386     example:
387         C<$layout->set_attr(attribute => value);>
388
389 =head2 get_text_wrap_cols()
390
391     Invoking the I<get_text_wrap_cols> method will return the number of columns that can be printed on the label before wrapping to the next line.
392
393     examples:
394         C<my $text_wrap_cols = $layout->get_text_wrap_cols();>
395
396 =head1 AUTHOR
397
398 Chris Nighswonger <cnighswonger AT foundations DOT edu>
399
400 =head1 COPYRIGHT
401
402 Copyright 2009 Foundations Bible College.
403
404 =head1 LICENSE
405
406 This file is part of Koha.
407
408 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
409 Foundation; either version 2 of the License, or (at your option) any later version.
410
411 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,
412 Suite 330, Boston, MA  02111-1307 USA
413
414 =head1 DISCLAIMER OF WARRANTY
415
416 Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
417 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
418
419 =cut