Bug 14468: Remove warnings when creating Labels
[koha.git] / C4 / Creators / Layout.pm
blob83274afb3efd44df1cc94a12cf086f5be4e04dbe
1 package C4::Creators::Layout;
3 use strict;
4 use warnings;
6 use autouse 'Data::Dumper' => qw(Dumper);
8 use C4::Context;
9 use C4::Debug;
10 use C4::Creators::PDF;
12 BEGIN {
13 use version; our $VERSION = qv('3.07.00.049');
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 # }
28 sub _check_params {
29 my $exit_code = 0;
30 my @valtmpl_id_params = (
31 'layout_id',
32 'barcode_type',
33 'printing_type',
34 'layout_name',
35 'guidebox',
36 'oblique_title',
37 'font',
38 'font_size',
39 'callnum_split',
40 'text_justify',
41 'format_string',
42 'layout_xml', # FIXME: all layouts should be stored in xml format to greatly simplify handling -chris_n
43 'creator',
44 'units',
45 'start_label',
47 if (scalar(@_) >1) {
48 my %given_params = @_;
49 foreach my $key (keys %given_params) {
50 if (!(grep m/$key/, @valtmpl_id_params)) {
51 warn sprintf('(Multiple parameters) Unrecognized parameter type of "%s".', $key);
52 $exit_code = 1;
56 else {
57 if (!(grep m/$_/, @valtmpl_id_params)) {
58 warn sprintf('(Single parameter) Unrecognized parameter type of "%s".', $_);
59 $exit_code = 1;
62 return $exit_code;
65 use constant PRESET_FIELDS => [qw(title author isbn issn itemtype barcode itemcallnumber)];
66 sub new {
67 my $invocant = shift;
68 my $self = '';
69 if (_check_params(@_) eq 1) {
70 return -1;
72 my $type = ref($invocant) || $invocant;
73 if (grep {$_ eq 'Labels'} @_) {
74 $self = {
75 layout_xml => '',
76 units => 'POINT',
77 start_label => 1,
78 barcode_type => 'CODE39',
79 printing_type => 'BAR',
80 layout_name => 'DEFAULT',
81 guidebox => 0,
82 oblique_title => 1,
83 font => 'TR',
84 font_size => 3,
85 callnum_split => 0,
86 text_justify => 'L',
87 format_string => join(', ', @{ PRESET_FIELDS() }),
88 @_,
91 elsif (grep {$_ eq 'Patroncards'} @_) {
92 $self = {
93 layout_xml => '<opt>Default Layout</opt>',
94 @_,
97 bless ($self, $type);
98 return $self;
101 sub retrieve {
102 my $invocant = shift;
103 my %opts = @_;
104 my $type = ref($invocant) || $invocant;
105 my $query = "SELECT * FROM creator_layouts WHERE layout_id = ? AND creator = ?";
106 my $sth = C4::Context->dbh->prepare($query);
107 $sth->execute($opts{'layout_id'}, $opts{'creator'});
108 if ($sth->err) {
109 warn sprintf('Database returned the following error: %s', $sth->errstr);
110 return -1;
112 my $self = $sth->fetchrow_hashref;
113 bless ($self, $type);
114 return $self;
117 sub delete {
118 my $self = {};
119 my %opts = ();
120 my $call_type = '';
121 my @params = ();
122 if (ref($_[0])) {
123 $self = shift; # check to see if this is a method call
124 $call_type = 'C4::Labels::Layout->delete';
125 push @params, $self->{'layout_id'}, $self->{'creator'};
127 else {
128 my $class = shift;
129 %opts = @_;
130 $call_type = $class . '::delete';
131 push @params, $opts{'layout_id'}, $opts{'creator'};
133 if (scalar(@params) < 2) { # If there is no layout id or creator type then we cannot delete it
134 warn sprintf('%s : Cannot delete layout as the profile id is invalid or non-existent.', $call_type) if !$params[0];
135 warn sprintf('%s : Cannot delete layout as the creator type is invalid or non-existent.', $call_type) if !$params[1];
136 return -1;
138 my $query = "DELETE FROM creator_layouts WHERE layout_id = ? AND creator = ?";
139 my $sth = C4::Context->dbh->prepare($query);
140 $sth->execute(@params);
141 if ($sth->err) {
142 warn sprintf('Database returned the following error on attempted DELETE: %s', $sth->errstr);
143 return -1;
147 sub save {
148 my $self = shift;
149 if ($self->{'layout_id'}) { # if we have an id, the record exists and needs UPDATE
150 my @params;
151 my $query = "UPDATE creator_layouts SET ";
152 foreach my $key (keys %{$self}) {
153 next if ($key eq 'layout_id') || ($key eq 'creator');
154 push (@params, $self->{$key});
155 $query .= "$key=?, ";
157 $query = substr($query, 0, (length($query)-2));
158 $query .= " WHERE layout_id=? AND creator = ?;";
159 push (@params, $self->{'layout_id'}, $self->{'creator'});
160 my $sth = C4::Context->dbh->prepare($query);
161 #local $sth->{TraceLevel} = "3"; # enable DBI trace and set level; outputs to STDERR
162 $sth->execute(@params);
163 if ($sth->err) {
164 warn sprintf('Database returned the following error: %s', $sth->errstr);
165 return -1;
167 return $self->{'layout_id'};
169 else { # otherwise create a new record
170 my @params;
171 my $query = "INSERT INTO creator_layouts (";
172 foreach my $key (keys %{$self}) {
173 push (@params, $self->{$key});
174 $query .= "$key, ";
176 $query = substr($query, 0, (length($query)-2));
177 $query .= ") VALUES (";
178 for (my $i=1; $i<=(scalar keys %$self); $i++) {
179 $query .= "?,";
181 $query = substr($query, 0, (length($query)-1));
182 $query .= ");";
183 my $sth = C4::Context->dbh->prepare($query);
184 $sth->execute(@params);
185 if ($sth->err) {
186 warn sprintf('Database returned the following error: %s', $sth->errstr);
187 return -1;
189 my $sth1 = C4::Context->dbh->prepare("SELECT MAX(layout_id) FROM creator_layouts;");
190 $sth1->execute();
191 my $id = $sth1->fetchrow_array;
192 $self->{'layout_id'} = $id;
193 return $id;
197 sub get_attr {
198 my $self = shift;
199 if (_check_params(@_) eq 1) {
200 return -1;
202 my ($attr) = @_;
203 if (exists($self->{$attr})) {
204 return $self->{$attr};
206 else {
207 return -1;
209 return;
212 sub set_attr {
213 my $self = shift;
214 if (_check_params(@_) eq 1) {
215 return -1;
217 my %attrs = @_;
218 foreach my $attrib (keys(%attrs)) {
219 $self->{$attrib} = $attrs{$attrib};
221 return 0;
224 sub get_text_wrap_cols {
225 my $self = shift;
226 my %params = @_;
227 my $string = '';
228 my $strwidth = 0;
229 my $col_count = 0;
230 my $textlimit = $params{'label_width'} - (( 3 * $params{'left_text_margin'} ) || 13.5 );
232 while ($strwidth < $textlimit) {
233 $string .= '8'; # using '8' as filling char instead of '0'
234 $col_count++;
235 $strwidth = C4::Creators::PDF->StrWidth( $string, $self->{'font'}, $self->{'font_size'} );
237 return $col_count;
241 __END__
243 =head1 NAME
245 C4::Labels::Layout -A class for creating and manipulating layout objects in Koha
247 =head1 ABSTRACT
249 This module provides methods for creating, retrieving, and otherwise manipulating label layout objects used by Koha to create and export labels.
251 =head1 METHODS
253 =head2 new()
255 Invoking the I<new> method constructs a new layout object containing the default values for a layout.
256 The following parameters are optionally accepted as key => value pairs:
258 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:
260 =over 9
262 =item .
263 CODE39 = Code 3 of 9
265 =item .
266 CODE39MOD = Code 3 of 9 with modulo 43 checksum
268 =item .
269 CODE39MOD10 = Code 3 of 9 with modulo 10 checksum
271 =item .
272 COOP2OF5 = A variant of 2 of 5 barcode based on NEC's "Process 8000" code
274 =item .
275 INDUSTRIAL2OF5 = The standard 2 of 5 barcode (a binary level bar code developed by Identicon Corp. and Computer Identics Corp. in 1970)
277 =back
279 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:
281 =over 9
283 =item .
284 BIB = Only the bibliographic data is printed
286 =item .
287 BARBIB = Barcode proceeds bibliographic data
289 =item .
290 BIBBAR = Bibliographic data proceeds barcode
292 =item .
293 ALT = Barcode and bibliographic data are printed on alternating labels
295 =item .
296 BAR = Only the barcode is printed
298 =back
300 C<layout_name> The descriptive name for this layout.
301 C<guidebox> Setting this to '1' will result in a guide box being drawn around the labels marking the edge of each label
302 C<font> Defines the type of font to be used on labels. NOTE: The following fonts are available by default on most systems:
304 =over 9
306 =item .
307 TR = Times-Roman
309 =item .
310 TB = Times Bold
312 =item .
313 TI = Times Italic
315 =item .
316 TBI = Times Bold Italic
318 =item .
319 C = Courier
321 =item .
322 CB = Courier Bold
324 =item .
325 CO = Courier Oblique (Italic)
327 =item .
328 CBO = Courier Bold Oblique
330 =item .
331 H = Helvetica
333 =item .
334 HB = Helvetica Bold
336 =item .
337 HBO = Helvetical Bold Oblique
339 =back
341 C<font_size> Defines the size of the font in postscript points to be used on labels
342 C<callnum_split> Setting this to '1' will enable call number splitting on labels
343 C<text_justify> Defines the text justification to be used on labels. NOTE: The following justification styles are currently supported by label creator code:
345 =over 9
347 =item .
348 L = Left
350 =item .
351 C = Center
353 =item .
354 R = Right
356 =back
358 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
359 to your MARC frameworks. Specify MARC subfields as a 4-character tag-subfield string: ie. 254a Enclose a whitespace-separated list of fields
360 to concatenate on one line in double quotes. ie. "099a 099b" or "itemcallnumber barcode" Static text strings may be entered in single-quotes:
361 ie. 'Some static text here.'
363 example:
364 C<my $layout = Layout->new(); # Creates and returns a new layout object>
366 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
367 the supplied values to override the defaults>
369 B<NOTE:> This layout is I<not> written to the database until save() is invoked. You have been warned!
371 =head2 retrieve(layout_id => layout_id)
373 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.
374 Errors are logged to the Apache log.
376 example:
377 C<my $layout = Layout->retrieve(layout_id => 1); # Retrieves layout record 1 and returns an object containing the record>
379 =head2 delete()
381 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.
382 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.
384 examples:
385 C<my $exitstat = $layout->delete(); # to delete the record behind the $layout object>
386 C<my $exitstat = Layout->delete(layout_id => 1); # to delete layout record 1>
388 =head2 save()
390 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.
391 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.
393 example:
394 C<my $exitstat = $layout->save(); # to save the record behind the $layout object>
396 =head2 get_attr($attribute)
398 Invoking the I<get_attr> method will return the value of the requested attribute or -1 on errors.
400 example:
401 C<my $value = $layout->get_attr($attribute);>
403 =head2 set_attr(attribute => value, attribute_2 => value)
405 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
406 commas.
408 example:
409 C<$layout->set_attr(attribute => value);>
411 =head2 get_text_wrap_cols()
413 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.
415 examples:
416 C<my $text_wrap_cols = $layout->get_text_wrap_cols();>
418 =head1 AUTHOR
420 Chris Nighswonger <cnighswonger AT foundations DOT edu>
422 =head1 COPYRIGHT
424 Copyright 2009 Foundations Bible College.
426 =head1 LICENSE
428 This file is part of Koha.
430 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
431 Foundation; either version 2 of the License, or (at your option) any later version.
433 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,
434 Fifth Floor, Boston, MA 02110-1301 USA.
436 =head1 DISCLAIMER OF WARRANTY
438 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
439 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
441 =cut