Using the Jasper Reports Server PHP Client with WordPress 

Table of Contents

1. Introduction 
2. PHP Script 
3. Breaking down the PHP Script
4. JavaScript Code
5. Sample Blog Post
6. Hosting


1. Introduction 

This document demonstrates how to use the PHP Client to connect JasperReports
Server data with the Wordpress CMS. Wordpress is a very popular PHP application
that allows plugins and extensions, so that you can write your own code for the
content on a page. Using the PHP wrapper, WordPress can interface with
the API to exchange information between a JasperReports Server
and a blog post.

The example in this document only covers the runReport feature, although the wrapper has
much more functionality, covering all endpoints of the API.

1.a.	Requirements: 
	- A webserver 
	- PHP >=5.3 PEAR packages required by the PHP Client (see README) 
	- WordPress blog (see WordPress Installation) 


2. PHP Script 

In order to receive data using the PHP wrapper, you must create and
host a .php file that you can make requests with. In this example, jQuery is
used to request data from a PHP script, and that data populates a drop down 
menu, as well as execute reports and return their data. 

Let's begin with the PHP script used to generate data from the server:

<?php
require_once('jasperclient/JasperClient.php');
 
class WPReport {
     
    public $client;
    private $mime_types = array(
            'html' => 'text/html',
            'pdf' => 'application/pdf',
            'xls' => 'application/vnd.ms-excel',
            'csv' => 'text/csv',
            'docx' => 'application/vnd.openxmlformats-
			officedocument.wordprocessingml.document',
            'rtf' => 'text/rtf',
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
            'xlsx' => 'application/vnd.ms-excel'
            );
 
    public function __construct() {
        $this->client = new Jasper\JasperClient('localhost', 8080, 
        'jasperadmin', 'jasperadmin', '/jasperserver-pro', 'organization_1');
    }
     
  
    /** 
     * run() is to be called via a GET parameter. Using run() will run a 
     report specified by URI and FORMAT get calls.
     * Example: 
     thisfile.php?func=run&uri=/reports/samples/AllAccounts&format=pdf
     * Calling the file in this manner will return the binary of the 
     specified report, in PDF format
     */
    public function run() {
        if(isset($_GET['uri']) && isset($_GET['format'])) {
            $report_data = $this->client->runReport($_GET['uri'], $_GET['format']);
            if ($_GET['format'] !== 'html') {
            echo $this->prepareForDownload($report_data, $_GET['format']);
            }
            else {
                echo $report_data;
            }
        }
    }
     
    /**
     * This function prepares a page with the proper headers to initiate 
     a download dialog in modern browsers
     * by using this function we can supply the report binary and users 
     can download the file
     */
    private function prepareForDownload($data, $format) {
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Description: File Transfer');
            header('Content-Disposition: attachment; 
    	filename=report.'.$format);
            header('Content-Transfer-Encoding: binary');
            header('Content-Length: ' . strlen($data));
            if(isset($this->mime_types[$format])) {
                header('Content-Type: ' . $this->mime_types[$format]);
            } else {
                header('Content-Type: application/octet-stream');
            }
            echo $data;
    }
    /**
     * This function returns the reports vailable at the position 'uri'
     * the data is echoed in JSON format so it can be used by a jQuery 
   function
     * to populate a dropdown select HTML element
     * example: thisfile.php?func=getReports&uri=/reports/samples
     */
    public function getReports() {
        if(isset($_GET['uri'])) {
            $result = array();
            $repo = $this->client->getRepository($_GET['uri']);
            foreach($repo as $r) {
                $result[] = array('name' => $r->getName(), 'uri' => 
                $r->getUriString());
            }
            echo json_encode($result);
        }
    }
    /**
     * This function simply json-ifys the array above to populate a 
  drop-down menu
     * select HTML element. This way it is easy to change the formats 
  available
     */
    public function getTypes() {
        $result = array();
        foreach($this->mime_types as $key => $val) {
            $result[] = array('name' => $key, 'value' => $val);
        }
        echo json_encode($result);
    }
} // WPReport
 
/* If the function exists in our class, and it is requested, then run it */
 
if(isset($_GET['func']) && 
    method_exists('WPReport', $_GET['func'])) {
        $r = new WPReport();
        $r->$_GET['func']();
}
?>
 

3.	Breaking down the PHP Script 

First, the beginning of the file defines variables that are needed by a class. $client will hold the client object through which commands to the Jaspersoft Reports Server can be made. The $mime_types array is used to map file extensions to their respective MIME types. This is used when serving files for download.

3.a.	The Run Function 

public function run() {
        if(isset($_GET['uri']) && isset($_GET['format'])) {
            $report_data = $this->client->runReport($_GET['uri'], 
          $_GET['format']);
            if ($_GET['format'] !== 'html') {
            echo $this->prepareForDownload($report_data, 
          $_GET['format']);
            }
            else {
                echo $report_data;
            }
        }
    }

This function is runs a report on the server, and serves
the data returned. When a URI and format are supplied in the URL
as GET parameters, this function uses the client object to request a report
from the server. If the report is requested in HTML, it is echoed. If it is any
other format but HTML, it is passed to a different function that sends the
proper headers along with the binary data so the file can be accepted for
download by a browser.


3.b.	The prepareForDownload Function

The prepareForDownload function is only used to prepare the headers to be sent
and echos the data from the server. This way when the file is retrieved, the
browser knows how large it is, what to do with it, what to name it, and other
data that signify a download dialog box.

The report is displayed. This data is retrieved from the run
function.

getReports / getTypes function
public function getReports() {
        if(isset($_GET['uri'])) {
            $result = array();
            $repo = $this->client->getRepository($_GET['uri']);
            foreach($repo as $r) {
                $result[] = array('name' => $r->getName(), 'uri' => 
             $r->getUriString());
            }
            echo json_encode($result);
        }
    }
 
    public function getTypes() {
        $result = array();
        foreach($this->mime_types as $key => $val) {
            $result[] = array('name' => $key, 'value' => $val);
        }
        echo json_encode($result);
    }
    
These two functions are used to prepare data for the jQuery script to populate 
the drop-down menus. The first function (getReports) uses getRepository to 
request all the reports' resourceDescriptors as 'uri' (defined by a GET 
variable). Then it takes this data, maps the name and URI to each other, and 
encodes it in a JSON format that can be easily consumed by JavaScript.

The getTypes function does the same, except it only uses the data in the
$mime_types array to supply the second drop-down menu item with the types that
can be taken. This data could easily be hard-coded into the HTML, but for
simplicity this function is used.

Outside the WPReport class
if(isset($_GET['func']) && 
    method_exists('WPReport', $_GET['func'])) {
        $r = new WPReport();
        $r->$_GET['func']();
}

These final lines of code interpret the GET data when the page is requested. It
executes the function determined by the GET parameter func and runs the
corresponding function. This way we don't have to maintain separate files for
each task.


4.	JavaScript Code 

This specific example uses JavaScript to improve the user experience when using
the report generator. It also prevents the page from reloading when requesting
different reports. Coupling the JavaScript with an iframe we can serve
the data generated by the prepareForDownload function without reloading the
page.

jQuery(function(){
 
    // Manage AJAX loading image
    jQuery('#loading').hide();
 
    jQuery('#loading').bind("ajaxStart", function(){
        jQuery(this).show();
    }).bind("ajaxStop", function() {
        jQuery(this).hide();
    });
     
    // populate the dropdown box for the names of the reports
    jQuery.getJSON("http://localhost/runreport.php?func=getReports&uri=
  /reports/samples",
        function(data){
            var sel = jQuery("#reportList").empty();
                jQuery.each(data, function(){
                    sel.append(jQuery("<option />").val(this.uri).
                  text(this.name));
        });
    });
     
    // populate the dropdown for types of export
    jQuery.getJSON("http://localhost/runreport.php?func=getTypes",
        function(data){
            var sel = jQuery("#exportList").empty();
                jQuery.each(data, function(){
                    sel.append(jQuery("<option />").val(this.name).
                  text(this.name));
        });
    });
     
    // on 'submit' get the report. display html in div, other formats activate 
  hidden iframe to trigger download
    jQuery('#repsub').on('click', function(event) {
        if (jQuery('#exportList').val() !== 'html') {
            document.getElementById("hFrame").src = 'http://localhost/
          runreport.php?func=run&uri='+jQuery('#reportList').val()+'
          &format='+jQuery('#exportList').val();
        } else {
            jQuery('#displayReport').load('/wordpress/wp-content/plugins/
          jasper/runreport.php?func=run&uri='+jQuery('#reportList').val()+
          '&format='+jQuery('#exportList').val());
        }
 
    });
     
});
 
4.a.	Ajax

A loading indicator is created and bound to ajaxStart, so it
is displayed whenever Ajax requests are being made. It is also set to hide when
Ajax requests stop being made.

The first getJSON function is used to populate the list of reports. It requests
the data in JSON format from our PHP script. As you can see in the URL, it
defines the function that is called, as well as the URI we wish to request
reports from. An example of the data this returns is:

[{"name":"AllAccounts","uri":"\/reports\/samples\/AllAccounts"},
{"name":"Cascading_multi_select_report","uri":"\/reports\/samples\/Cascading_multi_select_report"},
{"name":"Department","uri":"\/reports\/samples\/Department"},
{"name":"EmployeeAccounts","uri":"\/reports\/samples\/EmployeeAccounts"},
{"name":"Employees","uri":"\/reports\/samples\/Employees"},
{"name":"FlashChartReport","uri":"\/reports\/samples\/FlashChartReport"},
{"name":"FlashMapReport","uri":"\/reports\/samples\/FlashMapReport"},
{"name":"FlashWidgetReport","uri":"\/reports\/samples\/FlashWidgetReport"},
{"name":"Freight","uri":"\/reports\/samples\/Freight"},
{"name":"PermissionsOfUsersWithARoleSharedByLoggedIn","uri":"\/reports\/samples\/PermissionsOfUsersWithARoleSharedByLoggedIn"},
{"name":"SalesByMonth","uri":"\/reports\/samples\/SalesByMonth"},
{"name":"StandardChartsAegeanReport","uri":"\/reports\/samples\/StandardChartsAegeanReport"},
{"name":"StandardChartsEyeCandyReport","uri":"\/reports\/samples\/StandardChartsEyeCandyReport"},
{"name":"StandardChartsReport","uri":"\/reports\/samples\/StandardChartsReport"}] 

Luckily, this data makes more sense to JavaScript/jQuery than it does to a person. This data is basically a listing of report names and their URIs that can be used to set the name and value attributes of the <option> element.

Data is transferred from the PHP script to the second drop down menu in the same way as shown in the next getJSON function.

jQuery('#repsub').on('click', function(event) {
        if (jQuery('#exportList').val() !== 'html') {
            document.getElementById("hFrame").src = 'http://localhost
          /runreport.php?func=run&uri='+jQuery('#reportList').val()+'&format=
          '+jQuery('#exportList').val();
        } else {
            jQuery('#displayReport').load('http://localhost/runreport.php
          ?func=run&uri='+jQuery('#reportList').val()+'&format'
          +jQuery('#exportList').val());
        }
 
    });

This final function is bound to the Submit button. When it is clicked, two
things can occur. The values chosen in the drop-down menus are taken using the
.val() function and are used to fill in the GET arguments for the PHP script's
URI and format options. Thus, if the report type is HTML, when the button is pressed, a DIV element is filled with the HTML produced by the script. Otherwise, we set the SRC attribute of a hidden iframe (id = hFrame) to the script. This is necessary because the headers must be the first thing served if a download dialog box is displayed. So by loading it through an iframe we are not bogged down by previously-loaded blog data.

5. Sample Blog Post 

We now need a user-facing form in HTML that incorporates the previous two scripts. To do this, add a new post with some HTML. If you are having trouble writing HTML in your posts, you might want to disable WordPress's visual text editor (Admin Panel > Users > Your Profile > Disable visual editor).

Use the following code in your post:

	<div id="reportBox">
	<h3 class="widget-title">View My Reports</h3>
	<label for="reportList"> Report name: </label>
	<select id="reportList" style="width:150px;">
	<!-- populated by jquery -->
	</select>
	<label for="exportList"> Download as: </label> <br>
	<select id="exportList">
	<!-- populated by jquery -->
	</select>
	<input name="submit" id="repsub" type="submit" value="submit" /> 
	  <label for="repsub" id="loading" > 
	  <img src="http://localhost/ajax-loader.gif" />  </label>
	<div id="displayReport">
	</div>
	<iframe style="display:none" id="hFrame"></i
	</div>
 
<!-- Scripts Below -->
 
<script type="application/javascript" 
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"> 
</script>
<script src="http://localhost/script.js" 
type="application/javascript"></script>

Loading the JavaScript, the menus are populated, and the Submit button
becomes active.

6. Hosting
 
The JavaScript file can be hosted anywhere accessible to the browser attempting
to use it. The PHP script must be accessible to the browser using the site, as
well as the server hosting the WordPress blog. In this example we use full paths
to define the location of these scripts. However, it's fine to use relative paths in the correct context. The PHP client must be accessible to the PHP script so it can be included properly. To make that happen, you might need to adjust the require_once() function to match your environment.



_________________________
Part Number: 1112-JSP50-1

Copyright (C) 2012 Jaspersoft Corporation. All rights reserved.
Printed in the U.S.A. Jaspersoft, the Jaspersoft logo,
Jaspersoft iReport Designer, JasperReports Library,
JasperReports Server, Jaspersoft OLAP, and Jaspersoft ETL
are trademarks and/or registered trademarks of Jaspersoft
Corporation in the United States and in jurisdictions
throughout the world. All other company and product names are
or may be trade names or trademarks of their respective owners.