Initial Commit of AgileBill Open Source

This commit is contained in:
unknown
2008-11-26 14:50:40 -08:00
parent ae5a0fc25e
commit 02306ccc47
2954 changed files with 410976 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,681 @@
<?php
/**
* AgileBill - Open Billing Software
*
* This body of work is free software; you can redistribute it and/or
* modify it under the terms of the Open AgileBill License
* License as published at http://www.agileco.com/agilebill/license1-4.txt
*
* For questions, help, comments, discussion, etc., please join the
* Agileco community forums at http://forum.agileco.com/
*
* @link http://www.agileco.com/
* @copyright 2004-2008 Agileco, LLC.
* @license http://www.agileco.com/agilebill/license1-4.txt
* @author Tony Landis <tony@agileco.com> and Thralling Penguin, LLC <http://www.thrallingpenguin.com>
* @package AgileBill
* @version 1.4.93
*/
class BASE_ReportFormatter {
var $output_path;
var $output;
function setOutputDirectory($d)
{
$this->output_path = $d;
}
function getOutput()
{
return $this->output;
}
}
class HTML_ReportFormatter extends BASE_ReportFormatter {
var $indent = 0;
var $coldata;
var $level;
var $div_count;
function setLevel(&$level)
{
$this->level =& $level;
}
function setIndent($amount)
{
if($amount == "") return;
$this->indent = $amount;
}
function addRow()
{
$this->coldata = array();
echo " <tr>\n";
}
function endRow()
{
/* output the coldata */
#if($this->indent) {
# echo " <td width=\"{$this->indent}\">&nbsp;</td>\n";
#}
$w = 100 / count($this->coldata);
foreach($this->coldata as $col) {
$tag = "td";
if (is_a($col[1],'ReportStyle')) {
$s = "style=\"".$col[1]->doHTML()."\"";
if($col[1]->is_heading) $tag = "th scope=\"col\"";
} else {
$s = "";
}
echo " <{$tag} {$s} width=\"{$w}%\">\n";
echo " {$col[0]}\n";
echo " </{$tag}>\n";
}
echo " </tr>\n";
}
function addColumn($col, $style = '')
{
/* take a column and a style */
$this->coldata[] = array($col, $style);
}
function addTable($style, $heading)
{
$i = $this->indent / 30; if($i<0) $i = 0;
++$i;
$this->div_count = 0;
if($style != 'report_heading') {
echo '<div id="level_'.$i.'">';
$this->div_count += 1;
}
if($this->indent == 0) {
if($style != 'level') {
echo '<div id="'.$style.'">';
$this->div_count += 1;
}
}
echo $heading;
echo '<table width="100%" border="0" cellspacing="0">';
echo "\n";
}
function endTable()
{
$i = $this->indent / 30; if($i<0) $i = 0;
++$i;
echo "</table>\n";
if($this->div_count == 1)
echo "</div>\n";
if($this->indent == 0) {
if($this->div_count == 2)
echo "</div>\n";
}
}
function startDocument($title = '')
{
ob_start();
echo "<html>\n";
echo "<head>\n";
echo "<title>{$title}</title>\n";
echo "<link rel=\"stylesheet\" href=\"".URL."themes/default_admin/report_style.css\" type=\"text/css\">";
echo "</head>\n<body>\n";
}
function endDocument()
{
echo "</body>\n</html>\n";
$content = ob_get_contents();
ob_end_clean();
$this->output = $this->output_path."/report.html";
$fp = fopen($this->output,'w');
if($fp) {
fwrite($fp,$content);
fclose($fp);
} else {
echo 'Could not write to output file.';
}
}
function addBreak()
{
echo "<br /><br /><br />";
}
function insertImage($file,$width,$height)
{
$file = basename($file);
echo "<center><img src=\"$file\" width=\"$width\" height=\"$height\" /></center>\n";
}
function write($s)
{
echo $s;
}
}
/**
* Outputs the report in DOS text format
*/
class TXT_ReportFormatter extends BASE_ReportFormatter {
var $indent = 0;
var $aindent;
var $coldata;
var $level;
function setLevel(&$level)
{
$this->level =& $level;
}
function setIndent($amount)
{
if($amount == "") return;
$this->indent = $amount;
}
function addRow()
{
$this->coldata = array();
}
function endRow()
{
/* output the coldata */
if($this->indent) {
$n = intval($this->indent) / 30;
echo str_repeat(" ", $n);
}
$w = (100 / count($this->coldata))/100 * 80;
foreach($this->coldata as $col) {
echo str_pad($col[0], $w);
}
echo "\r\n";
}
function addColumn($col, $style = '')
{
/* take a column and a style */
$this->coldata[] = array($col, $style);
}
function addTable($style, $heading=false)
{
if($this->indent) {
echo "\r\n";
$this->aindent = $this->indent;
} else {
echo "\r\n\r\n";
}
}
function endTable()
{
if($this->indent && $this->indent != $this->aindent) echo "\r\n";
}
function startDocument($title = '')
{
ob_start();
}
function endDocument()
{
$content = ob_get_contents();
ob_end_clean();
$this->output = $this->output_path."/report.txt";
$fp = fopen($this->output,'w');
if($fp) {
fwrite($fp,$content);
fclose($fp);
} else {
echo 'Could not write to output file.';
}
}
function addBreak()
{
echo "\r\n\r\n";
}
function insertImage($file,$width,$height)
{
$file = basename($file);
echo "\r\nSee file: $file\r\n";
}
function write($s)
{
}
}
class PDF_ReportFormatter extends BASE_ReportFormatter {
var $indent = 0;
var $aindent;
var $coldata;
var $pdf;
var $y;
var $level;
function write($s)
{
}
function setIndent($amount)
{
if($amount == "") return;
$this->indent = intval($amount);
}
function addRow()
{
$this->coldata = array();
}
function endRow()
{
$x = 9;
$n = 0;
/* output the coldata */
if($this->indent) {
$n = $this->indent / 30;
$x += ($n * 9);
}
$w = round((100 / count($this->coldata))/100 * (190 - ($n*9)));
$tx = $x;
foreach($this->coldata as $col) {
if (is_a($col[1],'ReportStyle')) {
/* set the bounding area */
$col[1]->setBounds($tx,$this->y,$tx + $w,$this->y + 5);
$col[1]->doPDF($this->pdf);
} else {
$tmp = new ReportStyle;
$tmp->doPDF($this->pdf);
}
#echo "x={$tx} y={$this->y} data={$col[0]} style={$col[1]}<br>";
$this->pdf->Text($tx, $this->y,$col[0]);
$tx += $w;
}
$this->addY(5, true);
}
function addY($y, $repeatLabels = false)
{
$this->y += $y;
if ($this->y > 275) {
$this->pdf->AddPage();
$this->y = 5;
if($repeatLabels)
$this->level->addHeaderLabels();
}
}
function setLevel(&$level)
{
$this->level =& $level;
}
function addColumn($col, $style = '')
{
/* take a column and a style */
$this->coldata[] = array($col, $style);
}
function addTable($style, $heading='')
{
if($this->indent) {
$this->addY(5);
$this->aindent = $this->indent;
} else {
$this->addY(10);
}
# if we're close to the end, goto next page
if($this->y > 250) $this->addY(1000);
}
function endTable()
{
if($this->indent && $this->indent != $this->aindent) $this->addY(5);
}
function startDocument($title = '')
{
require_once(PATH_INCLUDES.'pdf/fpdi.php');
require_once(PATH_INCLUDES.'pdf/fpdf_tpl.php');
require_once(PATH_INCLUDES.'pdf/fpdf.php');
$this->pdf = new fpdi;
$this->pdf->addPage();
$this->y = 5;
}
function endDocument()
{
$file = $this->output_path."/report.pdf";
$this->output = $file;
$this->pdf->Output($file,'F');
}
function addBreak()
{
$this->addY(10);
}
function insertImage($file,$width,$height)
{
$w = $width / 11.81102 * 2.5;
$h = $height / 11.81102 * 2.5;
$y = $this->y + 5;
$x = 105 - ($w/2);
#echo 'Place image at 0,'.$y." $w x $h<br>";
$this->pdf->Image($file, $x, $y, $w, $h);
$this->y = $y + $h + 5;
}
}
class ReportStyle {
var $font_weight;
var $font_family;
var $font_height;
var $bg_color;
var $is_heading;
var $tx, $ty, $bx, $by;
function ReportStyle()
{
$this->font_weight = '';
$this->font_family = 'times';
$this->font_height = 10;
$this->is_heading = false;
}
function fontFamily($f)
{
$this->font_family = $f;
}
function fontHeight($h)
{
$this->font_height = $h;
}
function bold()
{
$this->font_weight = 'bold';
}
function backgroundColor($r,$g,$b)
{
$this->bg_color = array($r,$g,$b);
}
function setBounds($x1,$y1,$x2,$y2)
{
$this->tx = $x1; $this->ty = $y1;
$this->bx = $x2; $this->by = $y2;
#echo "BOUNDS: $x1 x $y1 x $x2 x $y2<br>";
}
/**
* Generates the PDF style
*/
function doPDF(&$pdf)
{
if(is_array($this->bg_color)) {
$x1 = $this->tx;
$y1 = $this->ty - ($this->font_height * 0.352777778);
$w = $this->bx - $this->tx;
$h = $this->by - $this->ty;
$pdf->SetFillColor($this->bg_color[0],$this->bg_color[1],$this->bg_color[2]);
$pdf->Rect($x1,$y1,$w,$h,'F');
#echo "BOX: $x1 x $y1 x $w x $h<br>";
}
$b = ($this->font_weight == 'bold' ? "B" : "");
$pdf->SetFont($this->font_family,$b,$this->font_height);
}
/**
* Generates the HTML style
*/
function doHTML()
{
$s = "font-family: {$this->font_family}; font-size: {$this->font_height}pt;";
if($this->font_weight == 'bold')
$s .= " font-weight: bold;";
if(is_array($this->bg_color)) {
$s .= " background-color: #";
$s .= str_pad(dechex($this->bg_color[0]), 2, '0', STR_PAD_LEFT);
$s .= str_pad(dechex($this->bg_color[1]), 2, '0', STR_PAD_LEFT);
$s .= str_pad(dechex($this->bg_color[2]), 2, '0', STR_PAD_LEFT);
$s .= ";";
}
$s="";
return $s;
}
}
/**
* This class is a adaptor pattern that serves to place a break in the formatting of the report.
*/
class Report_BreakAdaptor {
function display($grouping, $aggregate, &$formatter)
{
$formatter->addBreak();
}
}
require_once PATH_MODULES.'report/class.Level.php';
class Report_DivAdaptor extends Level_Base {
var $id;
var $lev_setting;
var $lev_fields;
var $lev_items;
var $indent_html;
var $SQL_filtered;
var $group_level;
var $grouping_criteria;
var $has_title;
var $formatter;
function display($grouping, $aggregate, &$formatter)
{
$this->formatter =& $formatter;
#echo "<div id=\"{$this->id}\">";
if(isset($this->lev_items) && is_array($this->lev_items)) {
foreach ($this->lev_items as $item) {
echo "<div id=\"{$this->id}\">";
$c = $this->formatter->indent;
$item->display($grouping, $aggregate, $this->formatter);
$this->formatter->indent = $c;
echo "</div>";
}
}
#echo "</div>";
}
}
class Reporting {
var $has_header;
var $rep_title;
var $rep_subtitle_1;
var $rep_subtitle_2;
var $rep_date_start;
var $rep_date_end;
var $rep_image_src;
var $rep_image_width;
var $rep_image_height;
var $rep_image_alt;
var $rep_desc;
var $rep_items;
var $rep_formatter;
function Reporting (&$formatter, $has_header = false)
{
$this->has_header = $has_header;
/*
TODO: Implement this crap at a later point
$this->rep_title = $rep_title;
$this->rep_subtitle_1 = $rep_subtitle_1;
$this->rep_subtitle_2 = $rep_subtitle_2;
$this->rep_date_start = $rep_date_start;
$this->rep_date_end = $rep_date_end;
$this->rep_desc = $rep_desc;
$this->rep_image_src = $rep_image_src;
$this->rep_image_width = $rep_image_width;
$this->rep_image_height = $rep_image_height;
$this->rep_image_alt = $rep_image_alt;
*/
$this->rep_formatter =& $formatter;
}
function setTitle($t, $style = '')
{
if($style=='') $style = new ReportStyle;
$style->fontHeight(16);
$style->fontFamily('arial');
$this->rep_title = array($t,$style);
}
function setSubtitle1($t, $style = '')
{
if($style=='') $style = new ReportStyle;
$style->fontHeight(14);
$style->fontFamily('arial');
$this->rep_subtitle_1 = array($t,$style);
}
function setSubtitle2($t, $style = '')
{
if($style=='') $style = new ReportStyle;
$style->fontHeight(12);
$style->fontFamily('arial');
$this->rep_subtitle_2 = array($t,$style);
}
function addBreak ()
{
$this->rep_items[] = new Report_BreakAdaptor;
}
function addDiv($id)
{
$item = new Report_DivAdaptor;
$item->id = $id;
$this->rep_items[] = $item;
}
function append (&$item)
{
$this->rep_items[] =& $item;
}
function display ()
{
$this->rep_formatter->startDocument($this->rep_title[0]);
if ($this->has_header) {
$this->displayHeader();
}
if(is_array($this->rep_items)) {
foreach ($this->rep_items as $item) {
$cur = $this->rep_formatter->indent;
$item->display(Null, Null, $this->rep_formatter);
$this->rep_formatter->indent = $cur;
}
}
$this->rep_formatter->endDocument();
}
function displayHeader ()
{
if(is_a($this->rep_formatter,'HTML_ReportFormatter')) {
if ($this->rep_title != '') {
echo '<h1>'.$this->rep_title[0].'</h1>';
}
if ($this->rep_subtitle_1 != '') {
echo '<h2>'.$this->rep_subtitle_1[0].'</h2>';
}
if ($this->rep_subtitle_2 != '') {
echo '<h3>'.$this->rep_subtitle_2[0].'</h3>';
}
} else {
$this->rep_formatter->addTable('report_heading');
if ($this->rep_image_src != '') {
echo "<td class='rc-rep-image-cell'>";
$width_html = '';
$height_html = '';
$alt_html = '';
if ($this->rep_image_width != '') {
$width_html = " width='$this->rep_image_width'";
}
echo "<td class='rc-rep-image-cell'$width_html>";
if ($this->rep_image_height != '') {
$height_html = " height='$this->rep_image_height'";
}
if ($this->rep_image_alt != '') {
$alt_html = " alt='$this->rep_image_alt'";
}
echo "<img class='rc-rep-image' src='$this->rep_image_src' $width_html $height_html $alt_html >
</td>";
}
$d = "";
if ($this->rep_title != '') {
$this->rep_formatter->addRow();
$this->rep_formatter->addColumn($this->rep_title[0],$this->rep_title[1]);
$this->rep_formatter->endRow();
}
if ($this->rep_subtitle_1 != '') {
$this->rep_formatter->addRow();
$this->rep_formatter->addColumn($this->rep_subtitle_1[0],$this->rep_subtitle_1[1]);
$this->rep_formatter->endRow();
}
if ($this->rep_subtitle_2 != '') {
$this->rep_formatter->addRow();
$this->rep_formatter->addColumn($this->rep_subtitle_2[0],$this->rep_subtitle_2[1]);
$this->rep_formatter->endRow();
}
# $d .= "<h3>Report generated on " . date("d/m/y") . "</h3>";
if ($this->rep_desc != '') {
$d .= "<h3>$this->rep_desc</h3>";
}
$this->rep_formatter->addRow();
$this->rep_formatter->addColumn(' ');
$this->rep_formatter->endRow();
$this->rep_formatter->endTable();
}
}
}
?>

View File

@@ -0,0 +1,420 @@
<?php
/**
* AgileBill - Open Billing Software
*
* This body of work is free software; you can redistribute it and/or
* modify it under the terms of the Open AgileBill License
* License as published at http://www.agileco.com/agilebill/license1-4.txt
*
* For questions, help, comments, discussion, etc., please join the
* Agileco community forums at http://forum.agileco.com/
*
* @link http://www.agileco.com/
* @copyright 2004-2008 Agileco, LLC.
* @license http://www.agileco.com/agilebill/license1-4.txt
* @author Tony Landis <tony@agileco.com> and Thralling Penguin, LLC <http://www.thrallingpenguin.com>
* @package AgileBill
* @version 1.4.93
*/
set_include_path(PATH_SEPARATOR.PATH_INCLUDES."pear");
require_once 'XML/Parser.php';
class reportColumnTag
{
var $type;
var $sql = '';
var $criteria = '';
var $orderby = '';
var $indent = 0;
var $display = '';
var $field = '';
var $aggregate = false;
var $width = '';
var $format = '';
var $group_children_by = false;
var $visible = true;
var $hide_dups = false;
var $condition = '';
var $sql_criteria = '';
var $total = false;
var $total_format = '';
var $link = '';
var $user_criteria_table = '';
var $user_criteria_col_id = '';
var $user_criteria_col_name = '';
var $user_criteria_date_format = 'Y-m';
var $user_criteria_type;
var $user_criteria;
var $user_criteria_aggregate;
function reportColumnTag()
{
$this->type = 'reportLevelTag';
$this->user_criteria = false;
}
}
class reportDatasetTag
{
var $type;
var $sql = '';
var $criteria = '';
var $orderby = '';
function reportDatasetTag()
{
$this->type = 'reportDatasetTag';
}
}
class ReportParser extends XML_Parser
{
// Holds a reference to the reporting root class
var $reportClass;
// Holds the cdata as we parse a given tag
var $cdata;
// Holds our processing objects in a first in - last out (FILO) manner
var $stack;
// Holds the fields the user may edit and change
var $user_criteria;
// Holds the fields the user has changed
var $user_criteria_data;
// Holds the fields that have been added
var $user_criteria_fields;
function ReportParser(&$reportClass)
{
static $uc;
static $ucd;
static $ucf;
$this->user_criteria =& $uc;
$this->user_criteria_data =& $ucd;
$this->user_criteria_fields =& $ucf;
# Create the user criteria fields as static members
if(!is_a($reportClass,'Reporting')) die('Parameter 1 must be a Reporting reference.');
# Save the Reporting reference
$this->reportClass =& $reportClass;
# Clear the cdata buffer
$this->cdata = "";
# Init the stack
$this->stack = array();
# Call into XML_Parser, to set us up the bomb. (See references on ALL YOUR BASE R BELONG TO US - Seriously, it's funny shit.)
parent::XML_Parser();
# Do NOT perform case foldering!
$this->folding = false;
}
function getUserCriteria()
{
return $this->user_criteria;
}
function setUserCriteria($field, $condition, $value)
{
#$this->user_criteria_fields[] = $field;
$this->user_criteria_data[] = array($field, $condition, $value);
}
function getUserCriteriaSQL($field,&$isAggregate)
{
$sql = "";
if(!is_array($this->user_criteria_data)) return '';
foreach($this->user_criteria as $uc) {
if($uc['name'] == $field) {
break;
}
}
foreach($this->user_criteria_data as $ucd) {
if($ucd[0] == $field) {
$db =& DB();
# format the field correctly
switch($uc['type']) {
case 'date':
case 'date_year_month':
$ucd[2] = date('Ym',$ucd[2]);
break;
case 'date_year':
$ucd[2] = date('Y',$ucd[2]);
break;
default:
break;
}
if(strpos(strtoupper($ucd[1]),'NULL') !== false) {
$sql .= $field." ".$ucd[1];
} else {
if(ereg("^[0-9]+$",$ucd[2]))
$sql .= $field." ".$ucd[1]." ".$ucd[2];
else
$sql .= $field." ".$ucd[1]." ".$db->qstr($ucd[2]);
}
$sql .= " AND ";
}
}
if(strlen($sql))
$sql = substr($sql,0,strlen($sql)-4);
$isAggregate = $uc['aggregate'];
return $sql;
}
function startHandler($xp, $name, $attr)
{
# Clear the cdata buffer
$this->cdata = "";
if($name == 'report' && !count($this->stack)) {
# initial outer report tag. set our start state.
$this->stack[] =& $this->reportClass;
return;
} else if($name == 'level') {
$this->stack[] = new Level;
} else if($name == 'graph') {
$this->stack[] = new LevelGraph(
$attr['title'],
intval($attr['width']),
intval($attr['height']),
$attr['type'],
@$attr['direction'],
@$attr['x_angle']
);
} else if($name == 'column') {
$this->stack[] = new reportColumnTag;
} else if($name == 'dataset') {
$this->stack[] = new reportDatasetTag;
} else if($name == 'break') {
$work =& $this->last($this->stack);
if($work) {
$work->addBreak();
}
} else if($name == 'div') {
$item = new Report_DivAdaptor;
$item->id = $attr['id'];
$this->stack[] =& $item;
} else if($name == 'user_criteria') {
$work =& $this->last($this->stack);
if($work && is_a($work,'reportColumnTag')) {
# validate the type
switch($attr['type']) {
case 'auto_affiliate':
case 'auto_account':
case 'menu':
case 'bool':
case 'text':
case 'date_year_month':
case 'date_year':
case 'date':
break;
default:
echo 'Error in user_criteria type.'; exit;
}
$work->user_criteria = true;
$work->user_criteria_type = $attr['type'];
$work->user_criteria_date_format = @$attr['date_format'];
$work->user_criteria_table = @$attr['table'];
$work->user_criteria_col_id = @$attr['col_id'];
$work->user_criteria_col_name = @$attr['col_name'];
$work->user_criteria_aggregate = @$attr['aggregate'];
}
}
#echo '<pre>startHandler: '.$name."\n\n".print_r($this->stack,true).'</pre>';
}
function endHandler($xp, $name)
{
if(strlen($this->cdata)) {
while(preg_match("/%%([A-Z1-2_]+)%%/", $this->cdata, $regs)>0) {
if(defined($regs[1])) {
$this->cdata = str_replace("%%".$regs[1]."%%", constant($regs[1]), $this->cdata);
}
}
}
#echo "endHandler:$name<br>";
$work =& $this->last($this->stack); array_pop($this->stack);
#echo "Class Type: ".get_class($work)."<br>";
#echo '<pre>endHandler: '.$name."\n\n".print_r($this->stack,true).'</pre>';
if($name == 'report' && count($this->stack)==1) {
#echo 'stack is empty. returning from endHandler.<br>';
return;
}
# Report
if(is_a($work,'Reporting')) {
if($name == 'title')
$work->setTitle($this->cdata);
else if($name == 'subtitle1')
$work->setSubtitle1($this->cdata);
else if($name == 'subtitle2')
$work->setSubtitle2($this->cdata);
}
# Level
if(is_a($work,'Level')) {
if($name == 'sql')
$work->setSql($this->cdata);
else if($name == 'criteria')
$work->setCriteria($this->cdata);
else if($name == 'orderby')
$work->setOrderby($this->cdata);
else if($name == 'indent')
$work->setIndent($this->cdata);
else if($name == 'title')
$work->setTitle($this->cdata);
else if($name == 'htmlstyle')
$work->setClass($this->cdata);
else if($name == 'level') {
$ltmp =& $work;
$work =& $this->last($this->stack); array_pop($this->stack);
# Do we have user criteria values on this?
if(is_array($this->user_criteria_data)) {
#echo '<pre>'.print_r($this->user_criteria_data,true).'</pre>';
$tmp = $this->user_criteria_data;
foreach($tmp as $f) {
$a = false;
$c = $this->getUserCriteriaSQL($f[0], $a);
#echo "<pre>c=$c\n".print_r($f,true).'</pre>';
if(strlen($c)) {
$ltmp->addFieldCriteria($c, $a, $f[0]);
}
}
#echo "<pre>".print_r($ltmp,true)."</pre>"; exit;
}
$work->append($ltmp);
}
}
if(is_a($work,'Report_DivAdaptor')) {
$ltmp =& $work;
$work =& $this->last($this->stack); array_pop($this->stack);
$work->append($ltmp);
}
if(is_a($work,'reportColumnTag')) {
if($name == 'display')
$work->display = $this->cdata;
else if($name == 'field')
$work->field = $this->cdata;
else if($name == 'aggregate')
$work->aggregate = $this->cdata == 'true' ? true : false;
else if($name == 'width')
$work->width = $this->cdata;
else if($name == 'format')
$work->format = $this->cdata;
else if($name == 'group_children_by')
$work->group_children_by = $this->cdata == 'true' ? true : false;
else if($name == 'visible')
$work->visible = $this->cdata == 'true' ? true : false;
else if($name == 'hide_dups')
$work->hide_dups = $this->cdata == 'true' ? true : false;
else if($name == 'sql')
$work->sql = $this->cdata;
else if($name == 'sql_criteria')
$work->sql_criteria = $this->cdata;
else if($name == 'condition')
$work->condition = $this->cdata;
else if($name == 'total')
$work->total = $this->cdata == 'true' ? true : false;
else if($name == 'total_format')
$work->total_format = $this->cdata;
else if($name == 'link')
$work->link = $this->cdata;
else if($name == 'column') {
$f =& $work;
$work =& $this->last($this->stack); array_pop($this->stack);
$work->addField($f->display, $f->field, $f->aggregate, $f->width,
$f->format, $f->group_children_by, $f->visible, $f->hide_dups,
'', false, '', false, $f->condition, '', $f->sql, $f->sql_criteria,
0, '', '', false, $f->total, '', $f->total_format, '', false, $f->link
);
# If this field has user_criteria=true, then add it to the avail array
if($f->user_criteria) {
#echo "<pre>Trying\n".print_r($this->user_criteria_fields,true).'</pre>';
if(!is_array($this->user_criteria_fields) || !in_array(str_replace('.','',$f->field),$this->user_criteria_fields)) {
$this->user_criteria[] = array(
'name' => $f->field,
'display' => $f->display,
'type' => $f->user_criteria_type,
'date_format' => $f->user_criteria_date_format,
'values' => '',
'table' => $f->user_criteria_table,
'col_id' => $f->user_criteria_col_id,
'col_name' => $f->user_criteria_col_name,
'aggregate' => $f->aggregate
);
$this->user_criteria_fields[] = str_replace('.','',$f->field);
#echo "<pre>LEVEL\n".print_r($this->user_criteria,true).'</pre>';
}
}
}
}
if(is_a($work,'LevelGraph')) {
if($name == 'title')
$work->setTitle($this->cdata);
else if($name == 'graph') {
# store the reference
$ltmp =& $work;
# pop the stack again
$work =& $this->last($this->stack); array_pop($this->stack);
# Do we have user criteria values on this?
if(is_array($this->user_criteria_data)) {
$tmp = $this->user_criteria_data;
foreach($tmp as $f) {
$a = false;
$c = $this->getUserCriteriaSQL($f[0], $a);
#echo "<pre>c=$c\n".print_r($f,true).'</pre>';
if(strlen($c)) {
$ltmp->addFieldCriteria($c, $a, $f[0]);
}
}
#echo "<pre>".print_r($ltmp,true)."</pre>"; exit;
}
# append this graph onto the level/report/graph below
$work->append($ltmp);
}
}
if(is_a($work,'reportDatasetTag')) {
if($name == 'criteria')
$work->criteria = $this->cdata;
else if($name == 'orderby')
$work->orderby = $this->cdata;
else if($name == 'sql')
$work->sql = $this->cdata;
else if($name == 'dataset') {
# store the reference
$d =& $work;
# pop the stack
$work =& $this->last($this->stack); array_pop($this->stack);
# add the dataset to the graph
$work->addDataset($d->sql, $d->criteria, $d->orderby);
}
}
# Push the worker object back onto the stack
$this->stack[] =& $work;
}
function cdataHandler($xp, $cdata)
{
$this->cdata .= $cdata;
}
/**
* Returns the true class reference from an array, unlike any PHP function
*/
function &last(&$array) {
if (!is_array($array))
return null;
if (!count($array))
return false; // like end()
return $array[count($array)-1];
}
}
?>

View File

@@ -0,0 +1,310 @@
<?php
/**
* AgileBill - Open Billing Software
*
* This body of work is free software; you can redistribute it and/or
* modify it under the terms of the Open AgileBill License
* License as published at http://www.agileco.com/agilebill/license1-4.txt
*
* For questions, help, comments, discussion, etc., please join the
* Agileco community forums at http://forum.agileco.com/
*
* @link http://www.agileco.com/
* @copyright 2004-2008 Agileco, LLC.
* @license http://www.agileco.com/agilebill/license1-4.txt
* @author Tony Landis <tony@agileco.com>
* @package AgileBill
* @version 1.4.93
*/
/**
* Agileco Report Module
*/
class report
{
/**
* Get the list of available modules
*/
function module_menu($VAR)
{
global $C_translate;
if(!empty($VAR['report_module']))
$default = $VAR['report_module'];
else
$default = false;
$return = '';
$path = PATH_AGILE . 'reports/';
chdir($path);
$dir = opendir($path);
$count = 0;
while ($file_name = readdir($dir))
{
if( $file_name != '..' && $file_name != '.' && !ereg(".xml", $file_name) && !ereg(".php", $file_name))
{
$name = $C_translate->translate('menu', $file_name, '');
if(empty($name) && eregi("^[a-zA-Z0-9\-\_]{1,}", $file_name)) $name = strtoupper($file_name);
if(!empty($name))
{
$return .= "<option value=\"{$file_name}\"";
if($default == $file_name) $return .= " selected";
$return .= ">{$name}</option>\n";
$count++;
}
}
}
if($count > 10) $count = 10;
echo '<select id="report_module" name="report_module" size="'.$count.'" onChange="submit()" multiple>';
if($count==0)
echo '<option value="">No Reports Available</option>';
echo $return;
echo '</select>';
}
/**
* Get the list of available reports
*/
function report_menu($VAR)
{
global$C_translate;
$C_xml = new CORE_xml;
if(empty($VAR['report_module'])) {
echo $C_translate->translate('no_reports','report','');
return;
} else {
$module = $VAR['report_module'];
}
if(!empty($VAR['report_template']))
$default = $VAR['report_template'];
else
$default = false;
$return = '<select id="report_template" name="report_template" width="150" size="5" onChange="submit()" multiple>';
$path = PATH_AGILE . 'reports/'.$module.'/';
chdir($path);
$dir = opendir($path);
$count = 0;
while ($file_name = readdir($dir))
{
if($file_name != '..' && $file_name != '.' && ereg(".xml$", $file_name)) {
$template = $C_xml->xml_to_array($path.$file_name);
$name = $template['report']['title'];
$return .= "<option value=\"{$file_name}\"";
if($default == $file_name) $return .= " selected";
$return .= ">{$name}</option>\n";
$count++;
}
}
if($count==0)
$return .= '<option value="">'. $C_translate->translate('no_reports','report','').'</option>';
$return .= '</select>';
echo $return;
}
/**
* Get user criteria
*/
function get_user_criteria($VAR)
{
# validation
if(empty($VAR['report_module']) || empty($VAR['report_template'])) return false;
$module = $VAR['report_module'];
$report = $VAR['report_template'];
# include reporting classess
require_once PATH_MODULES . 'report/class.Report.php';
require_once PATH_MODULES . 'report/class.Level.php';
require_once PATH_MODULES . 'report/class.ReportParser.php';
$f = new HTML_ReportFormatter;
$r = new Reporting($f, true);
$p = new ReportParser($r);
$result = $p->setInputFile(PATH_AGILE.'reports/'.$module.'/'.$report);
$result = $p->parse();
# pre-process the user criteria array
$arr = $p->getUserCriteria();
if(is_array($arr)) {
foreach($arr as $cond) {
if($cond['type']=='menu') {
//print_r($cond);
}
}
}
global $smarty;
$smarty->assign('userCriteria', $arr);
}
/**
* Set user criteria and display report
*/
function view($VAR)
{
# validation
if(empty($VAR['report_module']) || empty($VAR['report_template'])) return false;
$module = $VAR['report_module'];
$report = $VAR['report_template'];
$format = $VAR['report_format'];
# include reporting classess
require_once PATH_MODULES . 'report/class.Report.php';
require_once PATH_MODULES . 'report/class.Level.php';
require_once PATH_MODULES . 'report/class.ReportParser.php';
set_time_limit(0);
if($format=='text')
$f = new TXT_ReportFormatter;
elseif($format=='html')
$f = new HTML_ReportFormatter;
elseif($format=='pdf')
$f = new PDF_ReportFormatter;
# Tell the formatter where to save the output
$dir = md5(tempnam(PATH_FILES, "s"));
$path = PATH_FILES.'reports/'.$dir;
@unlink($path);
mkdir($path, 0775);
$f->setOutputDirectory($path);
# set report construct file to use
$r = new Reporting($f, true);
$p = new ReportParser($r);
$result = $p->setInputFile(PATH_AGILE.'reports/'.$module.'/'.$report);
# Get user criteria
$arr = $p->getUserCriteria();
# Set the user criteria
if(!empty($VAR['report']['conditions']) && is_array($VAR['report']['conditions'])) {
foreach($VAR['report']['conditions'] as $arr) {
$exp = $arr['exp'];
$col = $arr['col'];
$val = $arr['value'];
$type= $arr['type'];
foreach($col as $i=>$name) {
if($type[$i] == 'date_year_month') {
$val[$i] = array('month'=> $val['month'][$i], 'year'=> $val['year'][$i]);
}
$this->setSQLCondition($p, $col[$i], $exp[$i], $val[$i], $type[$i]);
}
}
}
#echo '<pre>'.print_r($p,true).'</pre>'; exit;
$result = $p->parse();
#echo '<pre>'.print_r($p,true).'</pre>'; exit;
$r->display();
if($format=='text') {
header('Content-type: text/txt');
header('Content-Disposition: inline; filename="report.txt"');
echo file_get_contents($f->getOutput());
@unlink($f->getOutput());
} elseif($format=='html') {
$f->getOutput();
$url=URL.'includes/files/reports/'.$dir.'/report.html';
echo "<script>document.location='$url';</script>";
} elseif ($format=='pdf') {
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="report.pdf"');
readfile($f->getOutput());
@unlink($f->getOutput());
}
}
/**
* Get actual SQL contition from user input and add to userCondtions
*/
function setSQLCondition(&$reportObj, $column, $condition, $value=false, $type=false)
{
$o["EQ"] = '=';
$o["NOT"] = '<>';
$o["GT"] = '>';
$o["LT"] = '<';
$o["GTEQ"] = '>=';
$o["LTEQ"] = '<=';
$o["LIKE"] = 'LIKE';
$o["NLIKE"] = 'IS NOT LIKE';
$o["NULL"] = 'IS NULL';
$o["NNULL"] = 'IS NOT NULL';
// actual SQL condition
$c = $o["$condition"];
// determine value
if( $condition=="NULL" || $condition=="NNULL" )
$v=false;
elseif ($value=='')
return false;
else
$v=$value;
if($type=='date') {
$v=$this->convert_date_time($value);
$reportObj->setUserCriteria($column, $c, $v);
} elseif ($type=='date_year') {
$v=mktime(0,0,0,1,1,$value);
$reportObj->setUserCriteria($column, $c, $v);
} elseif ($type=='date_year_month') {
if(!empty($value['year'])) {
if(empty($value['month'])) $month=1; else $month=$value['month'];
$v=mktime(0,0,0,$month,1,$value['year']);
$reportObj->setUserCriteria($column, $c, $v);
}
} else {
$reportObj->setUserCriteria($column, $c, $v);
}
}
/**
* convert DEFAULT_DATE_TIME_FORMT to unix time stamp
*/
function convert_date_time ($date, $constraint=false)
{
if($date == '0' || $date == '')
return '';
$Arr_format = split(DEFAULT_DATE_DIVIDER, UNIX_DATE_FORMAT);
$Arr_date = split(DEFAULT_DATE_DIVIDER, $date);
for($i=0; $i<3; $i++)
{
if($Arr_format[$i] == 'd')
$day = $Arr_date[$i];
if($Arr_format[$i] == 'm')
$month = $Arr_date[$i];
if($Arr_format[$i] == 'Y')
$year = $Arr_date[$i];
}
$timestamp = mktime(23, 59, 59, $month, $day, $year);
return $timestamp;
}
}
?>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<construct>
<!-- define the module name -->
<module>report</module>
<!-- define the module table name -->
<table>report</table>
<!-- define the module dependancy(s) -->
<dependancy/>
<!-- define the DB cache in seconds -->
<cache>0</cache>
<!-- define the default order_by field for SQL queries -->
<order_by>template,date_orig</order_by>
<!-- define the methods -->
<limit>35</limit>
<!-- define indexes -->
<index>
<nickname>nickname</nickname>
<template>template</template>
</index>
<!-- define the fields -->
<field>
<id>
<type>I4</type>
<unique>1</unique>
</id>
<site_id>
<type>C(16)</type>
</site_id>
<date_orig>
<type>I8</type>
<convert>date-time</convert>
</date_orig>
<date_last>
<type>I8</type>
<convert>date-now</convert>
</date_last>
<template>
<type>C(128)</type>
</template>
<nickname>
<type>C(32)</type>
<min_len>1</min_len>
<max_len>32</max_len>
</nickname>
<criteria>
<type>X2</type>
<convert>array</convert>
</criteria>
<module>
<type>C(32)</type>
</module>
</field>
<!-- define all the methods for this class, and the fields they have access to, if applicable. -->
<method>
<add>id,site_id,date_orig,date_last,template,nickname,criteria,module</add>
<update>id,site_id,date_orig,date_last,template,nickname,criteria,module</update>
<delete>id,site_id,date_orig,date_last,template,nickname,criteria,module</delete>
<view>id,site_id,date_orig,date_last,template,nickname,criteria,module</view>
<search>id,site_id,date_orig,date_last,template,nickname,criteria,module</search>
</method>
<!-- define the method triggers -->
<trigger>0</trigger>
</construct>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<install>
<!-- Define the main module properties -->
<module_properties>
<name>report</name>
<parent>report</parent>
<notes>Generate XML/XSL reports from the AgileBill database</notes>
<menu_display>1</menu_display>
<dependancy></dependancy>
<sub_modules></sub_modules>
</module_properties>
<!-- Define any SQL inserts for this module -->
<sql_inserts>
<module_method>
<view>
<name>view</name>
<page>%%:main</page>
<menu_display>1</menu_display>
</view>
<task_cleanup>
<name>task_cleanup</name>
</task_cleanup>
</module_method>
</sql_inserts>
</install>

56
modules/report/test.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
/*
AgileReports
(C) 2005-2006 Thralling Penguin LLC in association with Agileco LLC. All rights reserved.
*/
include "../../config.inc.php";
include PATH_INCLUDES."adodb/adodb.inc.php";
include PATH_MODULES."core/database.inc.php";
/*
There are features still missing! But it's not a shabby start.
*/
# these three files make up the reporting system
include 'class.Report.php';
include 'class.Level.php';
include 'class.ReportParser.php';
/* Good idea, reports can be a beast */
set_time_limit(0);
/* Uncomment one of the output formater lines below */
#$f = new TXT_ReportFormatter;
$f = new HTML_ReportFormatter;
#$f = new PDF_ReportFormatter;
# Tell the formatter where to save the output
$dir = tempnam(PATH_FILES, "s");
@unlink($dir);
mkdir($dir, 0775);
$f->setOutputDirectory($dir);
# This creates the report class, specifying the ReportFormatter to use and whether or not to paginate the title
$r = new Reporting($f, true);
# This creates the report XML parser, specify the report class object to use in building the report
$p = new ReportParser($r);
# This sets the XML report definition file
#$result = $p->setInputFile(PATH_MODULES.'report/year_month_sales_by_sku.xml');
$result = $p->setInputFile(PATH_AGILE.'reports/invoice/sales_report.xml');
# set criteria
$p->setUserCriteria('yearmonth','>=',mktime(0,0,0,1,1,2005));
# Parse that puppy!
$result = $p->parse();
/* COULD INSERT CODE TO DO SMARTY JUNK HERE - then skip the display call */
/* COULD ALSO call back into $p to assign some SQL statement criteria changes from the UI/Smarty's POST/GET */
# Render my report, now!
$r->display();
echo $f->getOutput();
?>