1 package C4::Creators::Lib;
3 # Copyright 2009 Foundations Bible College.
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 use autouse 'Data::Dumper' => qw(Dumper);
29 use version; our $VERSION = qv('1.0.0_1');
30 use base qw(Exporter);
31 our @EXPORT = qw(get_all_templates
41 get_text_justification_types
60 #=head2 C4::Creators::Lib::_SELECT()
62 # This function returns a recordset upon success and 1 upon failure. Errors are logged to the Apache log.
66 # my $field_value = _SELECT(field_name, table_name, condition);
72 my $query = "SELECT $params[0] FROM $params[1]";
73 $params[2] ? $query .= " WHERE $params[2];" : $query .= ';';
74 my $sth = C4::Context->dbh->prepare($query);
75 # $sth->{'TraceLevel'} = 3;
78 warn sprintf('Database returned the following error: %s', $sth->errstr);
82 while (my $row = $sth->fetchrow_hashref()) {
83 push(@$record_set, $row);
89 {type => 'CODE39', name => 'Code 39', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern.', selected => 0},
90 {type => 'CODE39MOD', name => 'Code 39 + Modulo43', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 43 checksum.', selected => 0},
91 {type => 'CODE39MOD10', name => 'Code 39 + Modulo10', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 10 checksum.', selected => 0},
92 {type => 'COOP2OF5', name => 'COOP2of5', desc => 'Creates COOP2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
93 # {type => 'EAN13', name => 'EAN13', desc => 'Creates EAN13 barcodes from a string of 12 or 13 digits. The check number (the 13:th digit) is calculated if not supplied.', selected => 0},
94 # {type => 'EAN8', name => 'EAN8', desc => 'Translates a string of 7 or 8 digits to EAN8 barcodes. The check number (the 8:th digit) is calculated if not supplied.', selected => 0},
95 # {type => 'IATA2of5', name => 'IATA2of5', desc => 'Creates IATA2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
96 {type => 'INDUSTRIAL2OF5', name => 'Industrial2of5', desc => 'Creates Industrial2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
97 # {type => 'ITF', name => 'Interleaved2of5', desc => 'Translates the characters 0-9 to a barcodes. These barcodes could also be called 'Interleaved2of5'.', selected => 0},
98 # {type => 'MATRIX2OF5', name => 'Matrix2of5', desc => 'Creates Matrix2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
99 # {type => 'NW7', name => 'NW7', desc => 'Creates a NW7 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
100 # {type => 'UPCA', name => 'UPCA', desc => 'Translates a string of 11 or 12 digits to UPCA barcodes. The check number (the 12:th digit) is calculated if not supplied.', selected => 0},
101 # {type => 'UPCE', name => 'UPCE', desc => 'Translates a string of 6, 7 or 8 digits to UPCE barcodes. If the string is 6 digits long, '0' is added first in the string. The check number (the 8:th digit) is calculated if not supplied.', selected => 0},
105 {type => 'BIB', name => 'Biblio', desc => 'Only the bibliographic data is printed.', selected => 0},
106 {type => 'BARBIB', name => 'Barcode/Biblio', desc => 'Barcode proceeds bibliographic data.', selected => 0},
107 {type => 'BIBBAR', name => 'Biblio/Barcode', desc => 'Bibliographic data proceeds barcode.', selected => 0},
108 {type => 'ALT', name => 'Alternating', desc => 'Barcode and bibliographic data are printed on alternating labels.', selected => 0},
109 {type => 'BAR', name => 'Barcode', desc => 'Only the barcode is printed.', selected => 0},
113 {type => 'TR', name => 'Times-Roman', selected => 0},
114 {type => 'TB', name => 'Times-Bold', selected => 0},
115 {type => 'TI', name => 'Times-Italic', selected => 0},
116 {type => 'TBI', name => 'Times-Bold-Italic', selected => 0},
117 {type => 'C', name => 'Courier', selected => 0},
118 {type => 'CB', name => 'Courier-Bold', selected => 0},
119 {type => 'CO', name => 'Courier-Oblique', selected => 0},
120 {type => 'CBO', name => 'Courier-Bold-Oblique', selected => 0},
121 {type => 'H', name => 'Helvetica', selected => 0},
122 {type => 'HB', name => 'Helvetica-Bold', selected => 0},
123 {type => 'HBO', name => 'Helvetica-Bold-Oblique', selected => 0},
126 my $text_justification_types = [
127 {type => 'L', name => 'Left', selected => 0},
128 {type => 'C', name => 'Center', selected => 0},
129 {type => 'R', name => 'Right', selected => 0},
130 # {type => 'F', name => 'Full', selected => 0},
134 {type => 'POINT', desc => 'PostScript Points', value => 1, selected => 0},
135 {type => 'AGATE', desc => 'Adobe Agates', value => 5.1428571, selected => 0},
136 {type => 'INCH', desc => 'US Inches', value => 72, selected => 0},
137 {type => 'MM', desc => 'SI Millimeters', value => 2.83464567, selected => 0},
138 {type => 'CM', desc => 'SI Centimeters', value => 28.3464567, selected => 0},
141 my $output_formats = [
142 {type => 'pdf', desc => 'PDF File'},
143 {type => 'csv', desc => 'CSV File'},
146 =head2 C4::Creators::Lib::get_all_templates()
148 my $templates = get_all_templates();
150 This function returns a reference to a hash containing all templates upon success and 1 upon failure. Errors are logged to the Apache log.
154 sub get_all_templates {
157 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_templates";
158 $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
159 my $sth = C4::Context->dbh->prepare($query);
162 warn sprintf('Database returned the following error: %s', $sth->errstr);
166 while (my $template = $sth->fetchrow_hashref) {
167 push(@templates, $template);
172 =head2 C4::Creators::Lib::get_all_layouts()
174 my $layouts = get_all_layouts();
176 This function returns a reference to a hash containing all layouts upon success and 1 upon failure. Errors are logged to the Apache log.
180 sub get_all_layouts {
183 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_layouts";
184 $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
185 my $sth = C4::Context->dbh->prepare($query);
188 warn sprintf('Database returned the following error: %s', $sth->errstr);
192 while (my $layout = $sth->fetchrow_hashref) {
193 push(@layouts, $layout);
198 =head2 C4::Creators::Lib::get_all_profiles()
200 my $profiles = get_all_profiles();
202 my $profiles = get_all_profiles(field_list => field_list, filter => filter_string);
204 This function returns an arrayref whose elements are hashes containing all profiles upon success and 1 upon failure. Errors are logged
205 to the Apache log. Two parameters are accepted. The first limits the field(s) returned. This parameter should be string of comma separted
206 fields. ie. "field_1, field_2, ...field_n" The second limits the records returned based on a string containing a valud SQL 'WHERE' filter.
208 NOTE: Do not pass in the keyword 'WHERE.'
212 sub get_all_profiles {
215 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM printers_profile";
216 $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
217 my $sth = C4::Context->dbh->prepare($query);
218 # $sth->{'TraceLevel'} = 3 if $debug;
221 warn sprintf('Database returned the following error: %s', $sth->errstr);
225 while (my $profile = $sth->fetchrow_hashref) {
226 push(@profiles, $profile);
231 =head2 C4::Creators::Lib::get_all_image_names()
235 sub get_all_image_names {
236 my $image_names = [];
237 my $query = "SELECT image_name FROM creator_images";
238 my $sth = C4::Context->dbh->prepare($query);
239 # $sth->{'TraceLevel'} = 3 if $debug;
242 warn sprintf('Database returned the following error: %s', $sth->errstr);
245 grep {push @$image_names, {type => $$_[0], name => $$_[0], selected => 0}} @{$sth->fetchall_arrayref([0])};
249 =head2 C4::Creators::Lib::get_batch_summary()
251 my $batches = get_batch_summary();
253 my $batches = get_batch_summary(filter => filter_string);
255 This function returns an arrayref whose elements are hashes containing the batch_ids of current batches along with the item count
256 for each batch upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
257 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
259 NOTE: Do not pass in the keyword 'WHERE.'
263 sub get_batch_summary {
266 my $query = "SELECT DISTINCT batch_id FROM creator_batches WHERE creator=?";
267 $query .= ($params{'filter'} ? " AND $params{'filter'};" : ';');
268 my $sth = C4::Context->dbh->prepare($query);
269 # $sth->{'TraceLevel'} = 3;
270 $sth->execute($params{'creator'});
272 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
276 while (my $batch = $sth->fetchrow_hashref) {
277 my $query = "SELECT count(batch_id) FROM creator_batches WHERE batch_id=? AND creator=?;";
278 my $sth1 = C4::Context->dbh->prepare($query);
279 $sth1->execute($batch->{'batch_id'}, $params{'creator'});
281 warn sprintf('Database returned the following error on attempted SELECT count: %s', $sth1->errstr);
284 my $count = $sth1->fetchrow_arrayref;
285 $batch->{'_item_count'} = @$count[0];
286 push(@batches, $batch);
291 =head2 C4::Creators::Lib::get_label_summary()
293 my $labels = get_label_summary();
295 my $labels = get_label_summary(items => @item_list);
297 This function returns an arrayref whose elements are hashes containing the label_ids of current labels along with the item count
298 for each label upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
299 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
301 NOTE: Do not pass in the keyword 'WHERE.'
305 sub get_label_summary {
307 my $label_number = 0;
308 my @label_summaries = ();
309 my $query = " SELECT b.title, b.author, bi.itemtype, i.barcode, i.biblionumber, i.itype
310 FROM creator_batches AS c LEFT JOIN items AS i ON (c.item_number=i.itemnumber)
311 LEFT JOIN biblioitems AS bi ON (i.biblioitemnumber=bi.biblioitemnumber)
312 LEFT JOIN biblio AS b ON (bi.biblionumber=b.biblionumber)
313 WHERE itemnumber=? AND batch_id=?;
315 my $sth = C4::Context->dbh->prepare($query);
316 foreach my $item (@{$params{'items'}}) {
318 $sth->execute($item->{'item_number'}, $params{'batch_id'});
320 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
323 my $record = $sth->fetchrow_hashref;
325 $label_summary->{'_label_number'} = $label_number;
326 $record->{'author'} =~ s/[^\.|\w]$// if $record->{'author'}; # strip off ugly trailing chars... but not periods or word chars
327 $record->{'title'} =~ s/\W*$//; # strip off ugly trailing chars
328 # FIXME contructing staff interface URLs should be done *much* higher up the stack - for the most part, C4 module code
329 # should not know that it's part of a web app
330 $record->{'title'} = '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' . $record->{'biblionumber'} . '"> ' . $record->{'title'} . '</a>';
331 $label_summary->{'_summary'} = $record->{'title'} . " | " . ($record->{'author'} ? $record->{'author'} : 'N/A');
332 $label_summary->{'_item_type'} = C4::Context->preference("item-level_itypes") ? $record->{'itype'} : $record->{'itemtype'};
333 $label_summary->{'_barcode'} = $record->{'barcode'};
334 $label_summary->{'_item_number'} = $item->{'item_number'};
335 $label_summary->{'_label_id'} = $item->{'label_id'};
336 push (@label_summaries, $label_summary);
338 return \@label_summaries;
341 =head2 C4::Creators::Lib::get_card_summary()
343 my $cards = get_card_summary();
345 my $cards = get_card_summary(items => @item_list);
347 This function returns an arrayref whose elements are hashes containing the label_ids of current cards along with the item count
348 for each card upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
349 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
351 NOTE: Do not pass in the keyword 'WHERE.'
355 sub get_card_summary {
358 my @card_summaries = ();
359 my $query = "SELECT CONCAT_WS(', ', surname, firstname) AS name, cardnumber FROM borrowers WHERE borrowernumber=?;";
360 my $sth = C4::Context->dbh->prepare($query);
361 foreach my $item (@{$params{'items'}}) {
363 $sth->execute($item->{'borrower_number'});
365 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
368 my $record = $sth->fetchrow_hashref;
369 my $card_summary->{'_card_number'} = $card_number;
370 $card_summary->{'_summary'} = $record->{'name'};
371 $card_summary->{'borrowernumber'} = $item->{'borrower_number'};
372 $card_summary->{'_label_id'} = $item->{'label_id'};
373 push (@card_summaries, $card_summary);
375 return \@card_summaries;
378 =head2 C4::Creators::Lib::get_barcode_types()
380 my $barcode_types = get_barcode_types();
382 This function returns a reference to an array of hashes containing all barcode types along with their name and description.
386 sub get_barcode_types {
387 return $barcode_types;
390 =head2 C4::Creators::Lib::get_label_types()
392 my $label_types = get_label_types();
394 This function returns a reference to an array of hashes containing all label types along with their name and description.
398 sub get_label_types {
402 =head2 C4::Creators::Lib::get_font_types()
404 my $font_types = get_font_types();
406 This function returns a reference to an array of hashes containing all font types along with their name and description.
414 =head2 C4::Creators::Lib::get_text_justification_types()
416 my $text_justification_types = get_text_justification_types();
418 This function returns a reference to an array of hashes containing all text justification types along with their name and description.
422 sub get_text_justification_types {
423 return $text_justification_types;
426 =head2 C4::Creators::Lib::get_unit_values()
428 my $unit_values = get_unit_values();
430 This function returns a reference to an array of hashes containing all unit types along with their description and multiplier.
431 NOTE: All units are relative to a PostScript Point.
432 There are 72 PS points to the inch.
436 sub get_unit_values {
440 =head2 C4::Creators::Lib::get_output_formats()
442 my $label_output_formats = get_output_formats();
444 This function returns a reference to an array of hashes containing all label output formats along with their description.
448 sub get_output_formats {
449 return $output_formats;
452 =head2 C4::Creators::Lib::get_column_names($table_name)
454 Return an arrayref of an array containing the column names of the supplied table.
458 sub get_column_names {
460 my $dbh = C4::Context->dbh();
461 my $column_names = [];
462 my $sth = $dbh->column_info(undef,undef,$table,'%');
463 while (my $info = $sth->fetchrow_hashref()){
464 $$column_names[$info->{'ORDINAL_POSITION'}] = $info->{'COLUMN_NAME'};
466 return $column_names;
469 =head2 C4::Creators::Lib::get_table_names($search_term)
471 Return an arrayref of an array containing the table names which contain the supplied search term.
475 sub get_table_names {
476 my $search_term = shift;
477 my $dbh = C4::Context->dbh();
478 my $table_names = [];
479 my $sth = $dbh->table_info(undef,undef,"%$search_term%");
480 while (my $info = $sth->fetchrow_hashref()){
481 push (@$table_names, $info->{'TABLE_NAME'});
486 =head2 C4::Creators::Lib::html_table()
488 This function returns an arrayref of an array of hashes contianing the supplied data formatted suitably to
489 be passed off as a T::P template parameter and used to build an html table.
491 my $table = html_table(header_fields, array_of_row_data);
499 <!-- TMPL_LOOP NAME="TABLE" -->
500 <!-- TMPL_IF NAME="header_fields" -->
502 <!-- TMPL_LOOP NAME="header_fields" -->
503 <th><!-- TMPL_VAR NAME="field_label" --></th>
508 <!-- TMPL_LOOP NAME="text_fields" -->
509 <!-- TMPL_IF NAME="select_field" -->
510 <td align="center"><input type="checkbox" name="action" value="<!-- TMPL_VAR NAME="field_value" -->" /></td>
511 <!-- TMPL_ELSIF NAME="field_value" -->
512 <td><!-- TMPL_VAR NAME="field_value" --></td>
527 return undef if scalar(@$data) == 0; # no need to generate a table if there is not data to display
530 my @table_columns = ();
531 my ($row_index, $col_index) = (0,0);
532 my $cols = 0; # number of columns to wrap on
534 my $select_value = undef;
535 my $link_field = undef;
537 foreach my $header (@$headers) {
538 my @key = keys %$header;
539 if ($key[0] eq 'select' ) {
540 push (@table_columns, $key[0]);
541 $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
542 # do special formatting stuff....
543 $select_value = $header->{$key[0]}{'value'};
546 # do special formatting stuff....
547 $link_field->{$key[0]} = ($header->{$key[0]}{'link_field'} == 1 ? 1 : 0);
548 push (@table_columns, $key[0]);
549 $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
554 $$table[$row_index] = {header_fields => $fields};
556 $field_count *= scalar(@$data); # total fields to be displayed in the table
561 foreach my $db_row (@$data) {
563 foreach my $table_column (@table_columns) {
564 if (grep {$table_column eq $_} keys %$db_row) {
565 $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $db_row->{$table_column}};
569 elsif ($table_column =~ m/^_((.*)_(.*$))/) { # this a special case
570 my $table_name = get_table_names($2);
571 my $record_set = _SELECT($1, @$table_name[0], $2 . "_id = " . $db_row->{$2 . "_id"});
572 $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $$record_set[0]{$1}};
576 elsif ($table_column eq 'select' ) {
577 $$fields[$col_index] = {hidden => 0, select_field => 1, field_name => 'select', field_value => $db_row->{$select_value}};
580 $$table[$row_index] = {text_fields => $fields};
593 Chris Nighswonger <cnighswonger AT foundations DOT edu>