Bug 14059: Delete all export of get_column_names
[koha.git] / C4 / Creators / Lib.pm
blob3f4c617bd94cbbcab7333b69cb544f003f2905bf
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
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.
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.
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>.
20 use strict;
21 use warnings;
23 use autouse 'Data::Dumper' => qw(Dumper);
25 use C4::Context;
26 use C4::Debug;
28 BEGIN {
29 use version; our $VERSION = qv('3.07.00.049');
30 use base qw(Exporter);
31 our @EXPORT = qw(get_all_templates
32 get_all_layouts
33 get_all_profiles
34 get_all_image_names
35 get_batch_summary
36 get_label_summary
37 get_card_summary
38 get_barcode_types
39 get_label_types
40 get_font_types
41 get_text_justification_types
42 get_output_formats
43 get_table_names
44 get_unit_values
45 html_table
49 =head1 NAME
51 C4::Creators::Lib
53 =cut
55 =head1 FUNCTIONS
57 =cut
59 #=head2 C4::Creators::Lib::_SELECT()
61 # This function returns a recordset upon success and 1 upon failure. Errors are logged to the Apache log.
63 # examples:
65 # my $field_value = _SELECT(field_name, table_name, condition);
67 #=cut
69 sub _SELECT {
70 my @params = @_;
71 my $query = "SELECT $params[0] FROM $params[1]";
72 $params[2] ? $query .= " WHERE $params[2];" : $query .= ';';
73 my $sth = C4::Context->dbh->prepare($query);
74 # $sth->{'TraceLevel'} = 3;
75 $sth->execute();
76 if ($sth->err) {
77 warn sprintf('Database returned the following error: %s', $sth->errstr);
78 return 1;
80 my $record_set = [];
81 while (my $row = $sth->fetchrow_hashref()) {
82 push(@$record_set, $row);
84 return $record_set;
87 my $barcode_types = [
88 {type => 'CODE39', name => 'Code 39', desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern.', selected => 0},
89 {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},
90 {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},
91 {type => 'COOP2OF5', name => 'COOP2of5', desc => 'Creates COOP2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
92 {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},
93 # {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},
94 # {type => 'IATA2of5', name => 'IATA2of5', desc => 'Creates IATA2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
95 {type => 'INDUSTRIAL2OF5', name => 'Industrial2of5', desc => 'Creates Industrial2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
96 # {type => 'ITF', name => 'Interleaved2of5', desc => 'Translates the characters 0-9 to a barcodes. These barcodes could also be called 'Interleaved2of5'.', selected => 0},
97 # {type => 'MATRIX2OF5', name => 'Matrix2of5', desc => 'Creates Matrix2of5 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
98 # {type => 'NW7', name => 'NW7', desc => 'Creates a NW7 barcodes from a string consisting of the numeric characters 0-9', selected => 0},
99 # {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},
100 # {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},
103 my $label_types = [
104 {type => 'BIB', name => 'Biblio', desc => 'Only the bibliographic data is printed.', selected => 0},
105 {type => 'BARBIB', name => 'Barcode/Biblio', desc => 'Barcode proceeds bibliographic data.', selected => 0},
106 {type => 'BIBBAR', name => 'Biblio/Barcode', desc => 'Bibliographic data proceeds barcode.', selected => 0},
107 {type => 'ALT', name => 'Alternating', desc => 'Barcode and bibliographic data are printed on alternating labels.', selected => 0},
108 {type => 'BAR', name => 'Barcode', desc => 'Only the barcode is printed.', selected => 0},
111 my $font_types = [
112 {type => 'TR', name => 'Times-Roman', selected => 0},
113 {type => 'TB', name => 'Times-Bold', selected => 0},
114 {type => 'TI', name => 'Times-Italic', selected => 0},
115 {type => 'TBI', name => 'Times-Bold-Italic', selected => 0},
116 {type => 'C', name => 'Courier', selected => 0},
117 {type => 'CB', name => 'Courier-Bold', selected => 0},
118 {type => 'CO', name => 'Courier-Oblique', selected => 0},
119 {type => 'CBO', name => 'Courier-Bold-Oblique', selected => 0},
120 {type => 'H', name => 'Helvetica', selected => 0},
121 {type => 'HO', name => 'Helvetica-Oblique', 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},
133 my $unit_values = [
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.
152 =cut
154 sub get_all_templates {
155 my %params = @_;
156 my @templates = ();
157 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_templates";
158 $query .= ($params{'filter'} ? " WHERE $params{'filter'} " : '');
159 $query .= ($params{'orderby'} ? " ORDER BY $params{'orderby'} " : '');
160 my $sth = C4::Context->dbh->prepare($query);
161 $sth->execute();
162 if ($sth->err) {
163 warn sprintf('Database returned the following error: %s', $sth->errstr);
164 return -1;
166 ADD_TEMPLATES:
167 while (my $template = $sth->fetchrow_hashref) {
168 push(@templates, $template);
170 return \@templates;
173 =head2 C4::Creators::Lib::get_all_layouts()
175 my $layouts = get_all_layouts();
177 This function returns a reference to a hash containing all layouts upon success and 1 upon failure. Errors are logged to the Apache log.
179 =cut
181 sub get_all_layouts {
182 my %params = @_;
183 my @layouts = ();
184 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_layouts";
185 $query .= ($params{'filter'} ? " WHERE $params{'filter'} " : '');
186 $query .= ($params{'orderby'} ? " ORDER BY $params{'orderby'} " : '');
187 my $sth = C4::Context->dbh->prepare($query);
188 $sth->execute();
189 if ($sth->err) {
190 warn sprintf('Database returned the following error: %s', $sth->errstr);
191 return -1;
193 ADD_LAYOUTS:
194 while (my $layout = $sth->fetchrow_hashref) {
195 push(@layouts, $layout);
197 return \@layouts;
200 =head2 C4::Creators::Lib::get_all_profiles()
202 my $profiles = get_all_profiles();
204 my $profiles = get_all_profiles(field_list => field_list, filter => filter_string);
206 This function returns an arrayref whose elements are hashes containing all profiles upon success and 1 upon failure. Errors are logged
207 to the Apache log. Two parameters are accepted. The first limits the field(s) returned. This parameter should be string of comma separted
208 fields. ie. "field_1, field_2, ...field_n" The second limits the records returned based on a string containing a valud SQL 'WHERE' filter.
210 NOTE: Do not pass in the keyword 'WHERE.'
212 =cut
214 sub get_all_profiles {
215 my %params = @_;
216 my @profiles = ();
217 my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM printers_profile";
218 $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
219 my $sth = C4::Context->dbh->prepare($query);
220 # $sth->{'TraceLevel'} = 3 if $debug;
221 $sth->execute();
222 if ($sth->err) {
223 warn sprintf('Database returned the following error: %s', $sth->errstr);
224 return -1;
226 ADD_PROFILES:
227 while (my $profile = $sth->fetchrow_hashref) {
228 push(@profiles, $profile);
230 return \@profiles;
233 =head2 C4::Creators::Lib::get_all_image_names()
235 =cut
237 sub get_all_image_names {
238 my $image_names = [];
239 my $query = "SELECT image_name FROM creator_images";
240 my $sth = C4::Context->dbh->prepare($query);
241 # $sth->{'TraceLevel'} = 3 if $debug;
242 $sth->execute();
243 if ($sth->err) {
244 warn sprintf('Database returned the following error: %s', $sth->errstr);
245 return -1;
247 grep {push @$image_names, {type => $$_[0], name => $$_[0], selected => 0}} @{$sth->fetchall_arrayref([0])};
248 return $image_names;
251 =head2 C4::Creators::Lib::get_batch_summary()
253 my $batches = get_batch_summary();
255 my $batches = get_batch_summary(filter => filter_string);
257 This function returns an arrayref whose elements are hashes containing the batch_ids of current batches along with the item count
258 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.
259 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
261 NOTE: Do not pass in the keyword 'WHERE.'
263 =cut
265 sub get_batch_summary {
266 my %params = @_;
267 my @batches = ();
268 my $query = "SELECT batch_id,count(batch_id) as _item_count FROM creator_batches WHERE creator=?";
269 $query .= ($params{'filter'} ? " AND $params{'filter'}" : '');
270 $query .= " GROUP BY batch_id";
271 my $sth = C4::Context->dbh->prepare($query);
272 # $sth->{'TraceLevel'} = 3;
273 $sth->execute($params{'creator'});
274 if ($sth->err) {
275 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
276 return -1;
278 while (my $batch = $sth->fetchrow_hashref) {
279 push(@batches, $batch);
281 return \@batches;
284 =head2 C4::Creators::Lib::get_label_summary()
286 my $labels = get_label_summary();
288 my $labels = get_label_summary(items => @item_list);
290 This function returns an arrayref whose elements are hashes containing the label_ids of current labels along with the item count
291 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.
292 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
294 NOTE: Do not pass in the keyword 'WHERE.'
296 =cut
298 sub get_label_summary {
299 my %params = @_;
300 my $label_number = 0;
301 my @label_summaries = ();
302 my $query = " SELECT b.title, b.author, bi.itemtype, i.barcode, i.biblionumber, i.itype
303 FROM creator_batches AS c LEFT JOIN items AS i ON (c.item_number=i.itemnumber)
304 LEFT JOIN biblioitems AS bi ON (i.biblioitemnumber=bi.biblioitemnumber)
305 LEFT JOIN biblio AS b ON (bi.biblionumber=b.biblionumber)
306 WHERE itemnumber=? AND batch_id=?;
308 my $sth = C4::Context->dbh->prepare($query);
309 foreach my $item (@{$params{'items'}}) {
310 $label_number++;
311 $sth->execute($item->{'item_number'}, $params{'batch_id'});
312 if ($sth->err) {
313 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
314 return -1;
316 my $record = $sth->fetchrow_hashref;
317 my $label_summary;
318 $label_summary->{'_label_number'} = $label_number;
319 $record->{'author'} =~ s/[^\.|\w]$// if $record->{'author'}; # strip off ugly trailing chars... but not periods or word chars
320 $record->{'title'} =~ s/\W*$//; # strip off ugly trailing chars
321 # FIXME contructing staff interface URLs should be done *much* higher up the stack - for the most part, C4 module code
322 # should not know that it's part of a web app
323 $record->{'title'} = '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' . $record->{'biblionumber'} . '"> ' . $record->{'title'} . '</a>';
324 $label_summary->{'_summary'} = $record->{'title'} . " | " . ($record->{'author'} ? $record->{'author'} : 'N/A');
325 $label_summary->{'_item_type'} = C4::Context->preference("item-level_itypes") ? $record->{'itype'} : $record->{'itemtype'};
326 $label_summary->{'_barcode'} = $record->{'barcode'};
327 $label_summary->{'_item_number'} = $item->{'item_number'};
328 $label_summary->{'_label_id'} = $item->{'label_id'};
329 push (@label_summaries, $label_summary);
331 return \@label_summaries;
334 =head2 C4::Creators::Lib::get_card_summary()
336 my $cards = get_card_summary();
338 my $cards = get_card_summary(items => @item_list);
340 This function returns an arrayref whose elements are hashes containing the label_ids of current cards along with the item count
341 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.
342 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
344 NOTE: Do not pass in the keyword 'WHERE.'
346 =cut
348 sub get_card_summary {
349 my %params = @_;
350 my $card_number = 0;
351 my @card_summaries = ();
352 my $query = "SELECT CONCAT_WS(', ', surname, firstname) AS name, cardnumber FROM borrowers WHERE borrowernumber=?;";
353 my $sth = C4::Context->dbh->prepare($query);
354 foreach my $item (@{$params{'items'}}) {
355 $card_number++;
356 $sth->execute($item->{'borrower_number'});
357 if ($sth->err) {
358 warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
359 return -1;
361 my $record = $sth->fetchrow_hashref;
362 my $card_summary->{'_card_number'} = $card_number;
363 $card_summary->{'_summary'} = $record->{'name'};
364 $card_summary->{'borrowernumber'} = $item->{'borrower_number'};
365 $card_summary->{'_label_id'} = $item->{'label_id'};
366 push (@card_summaries, $card_summary);
368 return \@card_summaries;
371 =head2 C4::Creators::Lib::get_barcode_types()
373 my $barcode_types = get_barcode_types();
375 This function returns a reference to an array of hashes containing all barcode types along with their name and description.
377 =cut
379 sub get_barcode_types {
380 return $barcode_types;
383 =head2 C4::Creators::Lib::get_label_types()
385 my $label_types = get_label_types();
387 This function returns a reference to an array of hashes containing all label types along with their name and description.
389 =cut
391 sub get_label_types {
392 return $label_types;
395 =head2 C4::Creators::Lib::get_font_types()
397 my $font_types = get_font_types();
399 This function returns a reference to an array of hashes containing all font types along with their name and description.
401 =cut
403 sub get_font_types {
404 return $font_types;
407 =head2 C4::Creators::Lib::get_text_justification_types()
409 my $text_justification_types = get_text_justification_types();
411 This function returns a reference to an array of hashes containing all text justification types along with their name and description.
413 =cut
415 sub get_text_justification_types {
416 return $text_justification_types;
419 =head2 C4::Creators::Lib::get_unit_values()
421 my $unit_values = get_unit_values();
423 This function returns a reference to an array of hashes containing all unit types along with their description and multiplier.
424 NOTE: All units are relative to a PostScript Point.
425 There are 72 PS points to the inch.
427 =cut
429 sub get_unit_values {
430 return $unit_values;
433 =head2 C4::Creators::Lib::get_output_formats()
435 my $label_output_formats = get_output_formats();
437 This function returns a reference to an array of hashes containing all label output formats along with their description.
439 =cut
441 sub get_output_formats {
442 return $output_formats;
446 =head2 C4::Creators::Lib::get_table_names($search_term)
448 Return an arrayref of an array containing the table names which contain the supplied search term.
450 =cut
452 sub get_table_names {
453 my $search_term = shift;
454 my $dbh = C4::Context->dbh();
455 my $table_names = [];
456 my $sth = $dbh->table_info(undef,undef,"%$search_term%");
457 while (my $info = $sth->fetchrow_hashref()){
458 push (@$table_names, $info->{'TABLE_NAME'});
460 return $table_names;
463 =head2 C4::Creators::Lib::html_table()
465 This function returns an arrayref of an array of hashes contianing the supplied data formatted suitably to
466 be passed off as a template parameter and used to build an html table.
468 my $table = html_table(header_fields, array_of_row_data);
469 $template->param(
470 table_loop => $table,
473 html example:
475 <table>
476 [% FOREACH table_loo IN table_loop %]
477 [% IF ( table_loo.header_fields ) %]
478 <tr>
479 [% FOREACH header_field IN table_loo.header_fields %]
480 <th>[% header_field.field_label %]</th>
481 [% END %]
482 </tr>
483 [% ELSE %]
484 <tr>
485 [% FOREACH text_field IN table_loo.text_fields %]
486 [% IF ( text_field.select_field ) %]
487 <td><input type="checkbox" name="action" value="[% text_field.field_value %]"></td>
488 [% ELSE %]
489 <td>[% text_field.field_value %]</td>
490 [% END %]
491 [% END %]
492 </tr>
493 [% END %]
494 [% END %]
495 </table>
497 =cut
499 sub html_table {
500 my $headers = shift;
501 my $data = shift;
502 return undef if scalar(@$data) == 0; # no need to generate a table if there is not data to display
503 my $table = [];
504 my $fields = [];
505 my @table_columns = ();
506 my ($row_index, $col_index) = (0,0);
507 my $cols = 0; # number of columns to wrap on
508 my $field_count = 0;
509 my $select_value = undef;
510 my $link_field = undef;
511 POPULATE_HEADER:
512 foreach my $header (@$headers) {
513 my @key = keys %$header;
514 if ($key[0] eq 'select' ) {
515 push (@table_columns, $key[0]);
516 $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
517 # do special formatting stuff....
518 $select_value = $header->{$key[0]}{'value'};
520 else {
521 # do special formatting stuff....
522 $link_field->{$key[0]} = ($header->{$key[0]}{'link_field'} == 1 ? 1 : 0);
523 push (@table_columns, $key[0]);
524 $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
526 $field_count++;
527 $col_index++;
529 $$table[$row_index] = {header_fields => $fields};
530 $cols = $col_index;
531 $field_count *= scalar(@$data); # total fields to be displayed in the table
532 $col_index = 0;
533 $row_index++;
534 $fields = [];
535 POPULATE_TABLE:
536 foreach my $db_row (@$data) {
537 POPULATE_ROW:
538 foreach my $table_column (@table_columns) {
539 if (grep {$table_column eq $_} keys %$db_row) {
540 $$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}};
541 $col_index++;
542 next POPULATE_ROW;
544 elsif ($table_column =~ m/^_((.*)_(.*$))/) { # this a special case
545 my $table_name = get_table_names($2);
546 my $record_set = _SELECT($1, @$table_name[0], $2 . "_id = " . $db_row->{$2 . "_id"});
547 $$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}};
548 $col_index++;
549 next POPULATE_ROW;
551 elsif ($table_column eq 'select' ) {
552 $$fields[$col_index] = {hidden => 0, select_field => 1, field_name => 'select', field_value => $db_row->{$select_value}};
555 $$table[$row_index] = {text_fields => $fields};
556 $col_index = 0;
557 $row_index++;
558 $fields = [];
560 return $table;
564 __END__
566 =head1 AUTHOR
568 Chris Nighswonger <cnighswonger AT foundations DOT edu>
570 =cut