From 75f2aa4d162c0c76a82c1f2a1e3ba3e89f248a46 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 23 Apr 2014 10:26:45 -0700 Subject: [PATCH 1/2] Add static image charts using phantomjs and imagemagick. --- .../report_formats/ImagechartReportFormat.php | 52 +++++++++++++++++++ lib/PhpReports/Report.php | 14 ++--- lib/PhpReports/ReportFormatBase.php | 4 +- lib/PhpReports/ReportTypeBase.php | 4 +- lib/phantomjs/chart.js | 17 ++++++ 5 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 classes/report_formats/ImagechartReportFormat.php create mode 100644 lib/phantomjs/chart.js diff --git a/classes/report_formats/ImagechartReportFormat.php b/classes/report_formats/ImagechartReportFormat.php new file mode 100644 index 00000000..c6a4073d --- /dev/null +++ b/classes/report_formats/ImagechartReportFormat.php @@ -0,0 +1,52 @@ +options['has_charts']) return; + + $cachekey = FileSystemCache::generateCacheKey($report->getCacheKeyParameters(),'imagecharts'); + + $result = FileSystemCache::retrieve($cachekey); + if(!$result) { + // Generate phantomjs command + $pwd = trim(shell_exec('pwd')); + $cmd = "phantomjs ".$pwd."/lib/phantomjs/chart.js"; + $cmd .= " ".escapeshellarg(PhpReports::$request->base); + $cmd .= " ".escapeshellarg($report->report); + $cmd .= " ".escapeshellarg($_SERVER['QUERY_STRING']); + + // Determine viewport width/height + $fullwidth = isset($_REQUEST['width'])? $_REQUEST['width'] : 1024; + $width = 0; + $height = 0; + foreach($report->options['Charts'] as $chart) { + if(preg_match('/\%$/',$chart['width'])) $width = max($width,substr($chart['width'],0,-1)/100*$fullwidth); + else $width = max($width,preg_replace('/^([0-9]+)([^0-9].*)?$/','$1',$chart['width'])); + $height += preg_replace('/^([0-9]+)([^0-9].*)?$/','$1',$chart['height'])*1; + } + $cmd .= " ".floor($width)." ".floor($height); + + // Generate temporary filename in cache directory + if(!file_exists($pwd.'/cache/phatomjs/')) mkdir($pwd.'/cache/phantomjs/',0777,true); + $filename = $pwd.'/cache/phantomjs/'.preg_replace('/\//','.',$report->report).'.'.date('Y-m-d_H-i-s').'.png'; + $cmd .= " ".escapeshellarg($filename); + + // Take the screenshot with phantomjs + shell_exec($cmd); + + // Trim transparent border and whitespace + shell_exec('mogrify -trim +repage -trim +repage '.$filename); + + // Cache result and delete image file + $result = file_get_contents($filename); + unlink($filename); + FileSystemCache::store($cachekey, base64_encode($result), 600); + } + else { + $result = base64_decode($result); + } + + // Output image + header('Content-Type: image/png'); + echo $result; + } +} diff --git a/lib/PhpReports/Report.php b/lib/PhpReports/Report.php index 2c7df9b1..931c66de 100644 --- a/lib/PhpReports/Report.php +++ b/lib/PhpReports/Report.php @@ -103,13 +103,15 @@ public function addMacro($name, $value) { public function exportHeader($name,$params) { $this->exported_headers[] = array('name'=>$name,'params'=>$params); } - + public function getCacheKeyParameters() { + return array( + 'report'=>$this->report, + 'macros'=>$this->macros, + 'database'=>$this->options['Environment'] + ); + } public function getCacheKey() { - return FileSystemCache::generateCacheKey(array( - 'report'=>$this->report, - 'macros'=>$this->macros, - 'database'=>$this->options['Environment'] - ),'report_results'); + return FileSystemCache::generateCacheKey($this->getCacheKeyParameters(),'report_results'); } public function getReportTimesCacheKey() { return FileSystemCache::generateCacheKey($this->report,'report_times'); diff --git a/lib/PhpReports/ReportFormatBase.php b/lib/PhpReports/ReportFormatBase.php index 49f682b5..2e9599ee 100644 --- a/lib/PhpReports/ReportFormatBase.php +++ b/lib/PhpReports/ReportFormatBase.php @@ -1,6 +1,8 @@ Date: Thu, 24 Apr 2014 08:01:19 -0700 Subject: [PATCH 2/2] Add chart image email attachment. --- lib/PhpReports/PhpReports.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/PhpReports/PhpReports.php b/lib/PhpReports/PhpReports.php index b9beeb52..01bcd243 100644 --- a/lib/PhpReports/PhpReports.php +++ b/lib/PhpReports/PhpReports.php @@ -468,11 +468,13 @@ public static function emailReport() { $csv_link = str_replace('report/html/?','report/csv/?',$link); $table_link = str_replace('report/html/?','report/table/?',$link); $text_link = str_replace('report/html/?','report/text/?',$link); + $chart_link = str_replace('report/html/?','report/imagechart/?',$link); - // Get the CSV file attachment and the inline HTML table + // Get the CSV file attachment, the inline HTML table, and any chart images $csv = self::urlDownload($csv_link); $table = self::urlDownload($table_link); $text = self::urlDownload($text_link); + $chart = self::urlDownload($chart_link); $email_text = $body."\n\n".$text."\n\nView the report online at $link"; $email_html = "

$body

$table

View the report online at ".htmlentities($link)."

"; @@ -488,14 +490,24 @@ public static function emailReport() { ->addPart($email_html, 'text/html') ; + // CSV $attachment = Swift_Attachment::newInstance() ->setFilename('report.csv') ->setContentType('text/csv') ->setBody($csv) ; - $message->attach($attachment); + // Charts + if($chart) { + $attachment = Swift_Attachment::newInstance() + ->setFilename('charts.png') + ->setContentType('image/png') + ->setBody($chart) + ; + $message->attach($attachment); + } + // Create the Transport $transport = self::getMailTransport(); $mailer = Swift_Mailer::newInstance($transport);