Also, the report_dir should be named in a fashion to guarantee uniquness. I have used a java style naming system, so each report is named org.ccfls.REPORT_NAME. If Biblibre created custom reports, they would be named com.biblibre.REPORT_NAME and so on.
I should note this patch does not represent the finished product, it is still a work in progress. I'm hoping to get suggestions to further improve on it. Kyle http://www.kylehall.info Information Technology Crawford County Federated Library System ( http://www.ccfls.org ) On Tue, Jan 26, 2010 at 8:42 AM, Kyle Hall <kyle.m.h...@gmail.com> wrote: > Hello All, > I've written a new "Custom Reports" addition for Koha to allow Koha > users to trade more complicated reports that cannot be represented in > pure SQL. Here's how it works: > > Each report is downloaded as a .krz file. This filetype is just a zip > file with a specific structure ( sort of like .deb is ). > > The structure is like so: > report_dir / > report.ini > ( other report files ) > > Pretty simple, I should say. > > The report.ini file looks something like this: > name=Access PA > author=Kyle M Hall > description=A Report of the data necessary to fill out the Access PA > report form. > start=access_pa/step1.pl > > When a report.krz file is uploaded into Koha, it is extracted to > KOHA_ROOT/reports/custom_reports/ > > The custom_reports.pl script reads all the report.ini files it fines > and generates the list of available reports dynamically. > > Please let me know what you think. I'm in the process of rewriting all > my php-based reports in perl using this system. I've sent patches for > the three I've done so far. The Access PA report is the only one too > complicated to represent in pure SQL, but I like being able to have > one query and to be able to select the library. > > I would suggest making all report forms use GET methods. That way, the > reports can be cronned using a simple wget command. > > Please let me know what you think. > > Thanks, > Kyle > > http://www.kylehall.info > Information Technology > Crawford County Federated Library System ( http://www.ccfls.org ) > > > > > On Tue, Jan 26, 2010 at 8:32 AM, Kyle M Hall <kyle.m.h...@gmail.com> wrote: >> --- >> C4/Reports/Custom.pm | 138 >> ++++++++++++++++++++ >> .../prog/en/modules/reports/custom_reports.tmpl | 58 ++++++++ >> .../en/modules/reports/custom_reports_upload.tmpl | 66 ++++++++++ >> .../prog/en/modules/reports/reports-home.tmpl | 5 + >> reports/custom_reports.pl | 52 ++++++++ >> reports/custom_reports_upload.pl | 89 +++++++++++++ >> 6 files changed, 408 insertions(+), 0 deletions(-) >> create mode 100644 C4/Reports/Custom.pm >> create mode 100644 >> koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl >> create mode 100644 >> koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl >> create mode 100755 reports/custom_reports.pl >> create mode 100644 reports/custom_reports/empty >> create mode 100755 reports/custom_reports_upload.pl >> >> diff --git a/C4/Reports/Custom.pm b/C4/Reports/Custom.pm >> new file mode 100644 >> index 0000000..add811c >> --- /dev/null >> +++ b/C4/Reports/Custom.pm >> @@ -0,0 +1,138 @@ >> +package C4::Reports::Custom; >> + >> +# Copyright 2010 Kyle Hall >> +# >> +# This file is part of Koha. >> +# >> +# 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 >> +# Foundation; either version 2 of the License, or (at your option) any later >> +# version. >> +# >> +# 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 >> +# A PARTICULAR PURPOSE. See the GNU General Public License for more >> details. >> +# >> +# 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, >> +# Suite 330, Boston, MA 02111-1307 USA >> + >> +use strict; >> +use warnings; >> + >> +use CGI; >> +use Config::Simple; >> + >> +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); >> + >> +use C4::Context; >> +use C4::Output; >> +use C4::Dates; >> +use C4::Debug; >> + >> +BEGIN { >> + # set the version for version checking >> + $VERSION = 0.01; >> + require Exporter; >> + @ISA = qw(Exporter); >> + @EXPORT = qw( >> + GetReports >> + ); >> +} >> + >> +=head1 NAME >> + >> +C4::Reports::Custom - Module for loading and managing custom reports. >> + >> +=head1 SYNOPSIS >> + >> + use C4::Reports::Custom; >> + >> +=over 2 >> + >> +=cut >> + >> +=item GetReports() >> + >> +This will return a list of all the available reports >> + >> +Usage: my ( $reports_hasref, $reports_count ) = >> C4::Reports::Custom::GetReports(); >> + >> +=cut >> + >> +sub GetReports { >> + my @reports_ini = _GetReportsIniFiles(); >> + >> + my @reports; >> + foreach my $report_ini ( @reports_ini ) { >> + my $ini_hashref = _ParseReportIni( $report_ini ); >> + push( @reports, $ini_hashref ); >> + } >> + >> + my $count = @reports; >> + >> + return ( \...@reports, $count ); >> +} >> + >> +=item _GetReportsIniFiles() >> + >> +This will return an array of all the ini files for the custom reports. >> + >> +=cut >> + >> +sub _GetReportsIniFiles { >> + my $reports_dir = '/home/koha/kohaclone/reports/custom_reports/'; >> + opendir(DIRHANDLE, $reports_dir); >> + my @reports_dirs = readdir(DIRHANDLE); >> + closedir(DIRHANDLE); >> + >> + my @reports; >> + foreach my $report_dir ( @reports_dirs ) { >> + >> + my $report_path = $reports_dir . $report_dir; >> + >> + if ( -d $report_path ) { >> + my $ini_path = $report_path . '/report.ini'; >> + >> + if ( -f $ini_path ) { >> + push( @reports, $ini_path ); >> + } >> + >> + } >> + >> + } >> + >> + return ( @reports ); >> +} >> + >> +=item _ParseReportIni( $ini_path ) >> + >> +This will return a hasref of key/value pairs found in the ini file >> + >> +=cut >> + >> +sub _ParseReportIni { >> + my ( $ini_path ) = @_; >> + >> + my $ini; >> + >> + open( INIFILE, '<', $ini_path ) or die("Could not open file >> $ini_path"); >> + foreach my $line ( <INIFILE> ) { >> + my ( $key, $value ); >> + ( $key, $value ) = split(/=/, $line ); >> + $ini->{$key} = $value; >> + } >> + >> + return $ini; >> +} >> + >> +1; >> +__END__ >> + >> +=back >> + >> +=head1 AUTHOR >> + >> +Kyle M Hall <kyle.m.h...@gmail.com> >> + >> +=cut >> diff --git >> a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl >> b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl >> new file mode 100644 >> index 0000000..a5db511 >> --- /dev/null >> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports.tmpl >> @@ -0,0 +1,58 @@ >> +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> >> +<title>Koha › Reports › Custom Reports </title> >> +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> >> +<!-- TMPL_INCLUDE NAME="calendar.inc" --> >> +</head> >> + >> +<body> >> +<!-- TMPL_INCLUDE NAME="header.inc" --> >> +<!-- TMPL_INCLUDE NAME="circ-search.inc" --> >> + >> +<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> >> +› <a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a> >> +› <a href="/cgi-bin/koha/reports/custom_reports.pl">Custom >> Reports</a> >> +</div> >> + >> +<div id="doc3" class="yui-t1"> >> + <div id="bd"> >> + <div id="yui-main"> >> + <div class="yui-b"> >> + <div class="details"> >> + <h1>Custom Reports</h1> >> + >> + <!-- TMPL_IF NAME="ERROR_NO_REPORTS" >> --> >> + <h2>No Custom Reports >> Exist.</h2> >> + <p>Please upload one or more >> Koha Custom Reports files (.krz) before using.</p> >> + <!-- TMPL_ELSE --> >> + <table> >> + <tr> >> + <th>Name</th> >> + >> <th>Description</th> >> + <th>Run</th> >> + </tr> >> + >> + <!-- TMPL_LOOP >> NAME="REPORTS_LOOP" --> >> + <tr> >> + >> <td><!-- TMPL_VAR NAME="name" --></td> >> + >> <td><!-- TMPL_VAR NAME="description" --></td> >> + >> <td><a href="custom_reports/<!-- TMPL_VAR NAME="start" -->">Run >> Report</a></td> >> + </tr> >> + <!-- /TMPL_LOOP --> >> + </table> >> + <!-- /TMPL_IF --> >> + </div> >> + </div> >> + </div> >> + >> + <div class="yui-b noprint"> >> + <div id="navmenu"> >> + <ul id="navmenulist"> >> + <li><a >> href="custom_reports_upload.pl">Upload A Custom Report</a></li> >> + </ul> >> + </div> >> + </div> >> + </div> >> +</div> >> + >> + >> +<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" --> >> diff --git >> a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl >> b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl >> new file mode 100644 >> index 0000000..30ff908 >> --- /dev/null >> +++ >> b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/custom_reports_upload.tmpl >> @@ -0,0 +1,66 @@ >> +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> >> +<title>Koha › Reports › Custom Reports › Upload Custom >> Report >> + </title> >> +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> >> +<!-- TMPL_INCLUDE NAME="calendar.inc" --> >> +</head> >> + >> +<body> >> +<!-- TMPL_INCLUDE NAME="header.inc" --> >> +<!-- TMPL_INCLUDE NAME="circ-search.inc" --> >> + >> +<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> >> +› <a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a> >> +› <a href="/cgi-bin/koha/reports/custom_reports.pl">Custom >> Reports</a> >> +› Upload Custom Report >> +</div> >> + >> +<div id="doc3" class="yui-t2"> >> + <div id="bd"> >> + <div id="yui-main"> >> + <div class="yui-b"> >> + <div class="yui-g"> >> + <div class="yui-u first"> >> + <h1>Upload Custom Report</h1> >> + <!-- TMPL_IF name="ERRORS" --> >> + <div class="dialog alert"> >> + <!-- TMPL_LOOP name="ERRORS" --> >> + <!-- TMPL_IF name="NOTKRZ" --><li><b>The upload >> file does not appear to be a krz file. The extention is not '.krz'.</b></li> >> + <!-- TMPL_ELSIF name="NOWRITETEMP" --><li><b>This >> script is not able to create/write to the necessary temporary >> directory.</b></li> >> + <!-- TMPL_ELSIF name="EMPTYUPLOAD" --><li><b>The >> upload file appears to be empty.</b></li> >> + <!-- TMPL_ELSIF name="UZIPFAIL" --><li><b><!-- >> TMPL_VAR name="UZIPFAIL" --> failed to unpack.<br />Please verify the >> integrity of the zip file and retry.</b></li> >> + <!-- TMPL_ELSIF name="NOWRITEREPORTS" >> --><li><b>Cannot unpack file to the custom reports directory.<br />Please >> verify that the Apache user can write to the custom reports >> directory.</b></li> >> + <!-- TMPL_ELSE --><li><b><!-- TMPL_VAR name >> ="CORERR" --> An unknown error has occurred.<br />Please review the error >> log for more details.</b></li><!-- /TMPL_IF --> >> + <!-- /TMPL_LOOP --> >> + </div> >> + <!-- /TMPL_IF --> >> + <form method="post" >> action="/cgi-bin/koha/reports/custom_reports_upload.pl" >> enctype="multipart/form-data"> >> + <fieldset class="brief"> >> + <div class="hint"><b>NOTE:</b> Only KRZ file format >> is supported.</div> >> + <ol> >> + <li> >> + <label for="uploadfile">Select the file to >> upload: </label><input type="file" id="uploadfile" name="uploadfile" /> >> + </li> >> + </ol> >> + </li></ol> >> + </fieldset> >> + <fieldset class="action"> >> + <input type="hidden" name="op" value="Upload" /> >> + <input type="submit" value="Upload" class="submit" >> /> >> + </fieldset> >> + </form> >> + >> + </div> >> + </div> >> + </div> >> +</div> >> +<div class="yui-b noprint"> >> +<div id="navmenu"> >> + <ul id="navmenulist"> >> + <li><a href="/cgi-bin/koha/reports/custom_reports.pl">Custom >> Reports Home</a></li> >> + </ul> >> +</div> >> + >> +</div> >> +</div> >> +<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" --> >> diff --git >> a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl >> b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl >> index b2d8487..d97c8ef 100644 >> --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl >> +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl >> @@ -27,6 +27,11 @@ >> <li><a >> href="/cgi-bin/koha/reports/dictionary.pl?phase=View%20Dictionary">View >> Dictionary</a></li> >> </ul> >> >> + <h2>Custom Reports</h2> >> + <ul> >> + <li><a href="/cgi-bin/koha/reports/custom_reports.pl">Custom >> Reports</a></li> >> + </ul> >> + >> <h2>Statistics wizards</h2> >> <ul> >> <li><a >> href="/cgi-bin/koha/reports/acquisitions_stats.pl">Acquisitions</a></li> >> diff --git a/reports/custom_reports.pl b/reports/custom_reports.pl >> new file mode 100755 >> index 0000000..29e23a9 >> --- /dev/null >> +++ b/reports/custom_reports.pl >> @@ -0,0 +1,52 @@ >> +#!/usr/bin/perl >> + >> +# Copyright 2010 Kyle M Hall <kyle.m.h...@gmail.com> >> +# >> +# This file is part of Koha. >> +# >> +# 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 >> +# Foundation; either version 2 of the License, or (at your option) any later >> +# version. >> +# >> +# 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 >> +# A PARTICULAR PURPOSE. See the GNU General Public License for more >> details. >> +# >> +# 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, >> +# Suite 330, Boston, MA 02111-1307 USA >> + >> +use strict; >> +use warnings; >> + >> +use CGI; >> + >> +use C4::Reports::Custom; >> +use C4::Auth; >> +use C4::Output; >> +use C4::Dates; >> +use C4::Debug; >> + >> +my $input = new CGI; >> + >> +my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >> + { >> + template_name => "reports/custom_reports.tmpl", >> + query => $input, >> + type => "intranet", >> + authnotrequired => 0, >> + flagsrequired => { reports => "execute_reports" }, >> + debug => 1, >> + } >> +); >> + >> +my ( $reports_loop, $reports_count ) = GetReports(); >> + >> +$template->param( REPORTS_LOOP => $reports_loop ); >> + >> +unless ( $reports_count ) { >> + $template->param( ERROR_NO_REPORTS => 1 ); >> +} >> + >> +output_html_with_http_headers $input, $cookie, $template->output; >> diff --git a/reports/custom_reports/empty b/reports/custom_reports/empty >> new file mode 100644 >> index 0000000..e69de29 >> diff --git a/reports/custom_reports_upload.pl >> b/reports/custom_reports_upload.pl >> new file mode 100755 >> index 0000000..5bf98bf >> --- /dev/null >> +++ b/reports/custom_reports_upload.pl >> @@ -0,0 +1,89 @@ >> +#!/usr/bin/perl >> +# >> +# This file is part of Koha. >> +# >> +# 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 >> +# Foundation; either version 2 of the License, or (at your option) any later >> +# version. >> +# >> +# 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 >> +# A PARTICULAR PURPOSE. See the GNU General Public License for more >> details. >> +# >> +# 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, >> +# Suite 330, Boston, MA 02111-1307 USA >> + >> +use strict; >> +use warnings; >> + >> +use File::Temp; >> +use File::Copy; >> +use CGI; >> +use GD; >> + >> +use C4::Context; >> +use C4::Auth; >> +use C4::Output; >> +use C4::Members; >> +use C4::Debug; >> + >> +my $input = new CGI; >> + >> +my ($template, $loggedinuser, $cookie) >> + = get_template_and_user({template_name => >> "reports/custom_reports_upload.tmpl", >> + query => $input, >> + type => "intranet", >> + authnotrequired => 0, >> + flagsrequired => { reports => >> 'create_report'}, >> + debug => 1, >> + }); >> + >> +my $uploadfilename = $input->param('uploadfile'); >> +my $uploadfile = $input->upload('uploadfile'); >> +my $op = $input->param('op'); >> + >> +my ( $total, $handled, @counts, $tempfile, $tfh ); >> + >> +my %errors; >> + >> +if ( ($op eq 'Upload') && $uploadfile ) { >> + my $custom_reports_dir = "/home/koha/kohaclone/reports/custom_reports/"; >> + >> + my $dirname = File::Temp::tempdir( CLEANUP => 1); >> + $debug and warn "dirname = $dirname"; >> + >> + my $filesuffix = $1 if $uploadfilename =~ m/(\..+)$/i; >> + ( $tfh, $tempfile ) = File::Temp::tempfile( SUFFIX => $filesuffix, >> UNLINK => 1 ); >> + >> + $debug and warn "tempfile = $tempfile"; >> + >> + $errors{'NOTKRZ'} = 1 if ( $uploadfilename !~ /\.krz$/i ); >> + $errors{'NOWRITETEMP'} = 1 unless ( -w $dirname ); >> + $errors{'NOWRITEREPORTS'} = 1 unless ( -w $custom_reports_dir ); >> + $errors{'EMPTYUPLOAD'} = 1 unless ( length( $uploadfile ) > 0 ); >> + >> + if ( %errors ) { >> + $template->param( ERRORS => [ \%errors ] ); >> + } else { >> + while ( <$uploadfile> ) { >> + print $tfh $_; >> + } >> + close $tfh; >> + unless (system("unzip $tempfile -d $custom_reports_dir") == 0) { >> + $errors{'UZIPFAIL'} = $uploadfilename; >> + $template->param( ERRORS => [ \%errors ] ); >> + output_html_with_http_headers $input, $cookie, >> $template->output; >> + exit; >> + } >> + } >> +} elsif ( ($op eq 'Upload') && !$uploadfile ) { >> + warn "Problem uploading file or no file uploaded."; >> +} >> + >> +if ( $uploadfile && !%errors && !$template->param('ERRORS') ) { >> + print $input->redirect ("/cgi-bin/koha/reports/custom_reports.pl"); >> +} else { >> + output_html_with_http_headers $input, $cookie, $template->output; >> +} >> -- >> 1.5.6.5 >> >> > _______________________________________________ Koha-devel mailing list Koha-devel@lists.koha.org http://lists.koha.org/mailman/listinfo/koha-devel