Commit f5206f4b authored by David Metzler's avatar David Metzler
Browse files

Working report and template editing.

parent b1a5fc1e
......@@ -347,14 +347,14 @@ class Frx {
* @param $report_name
* @return FrxEditor <string, FrxEditor>
*/
static public function Editor($report_name = '') {
static public function Editor($report_name = '', $edit=TRUE) {
static $o='';
require_once('FrxEditor.inc');
if (!$o) {
$o = new FrxEditor($report_name);
$o = new FrxEditor($report_name, $edit);
}
else {
if ($report_name) $o->load($report_name) ;
if ($report_name) $o->load($report_name, $edit) ;
}
return $o;
}
......@@ -364,17 +364,18 @@ class Frx {
* @param $block_name
* @return FrxBlockEditor
*/
static public function BlockEditor($block_name = '') {
static public function BlockEditor($block_name = '', $edit=TRUE) {
static $o='';
require_once('FrxBlockEditor.inc');
if (!$o) {
$o = new FrxBlockEditor($block_name);
$o = new FrxBlockEditor($block_name, $edit);
}
else {
if ($block_name && $o->block_name != $block_name) $o->load($block_name);
if ($block_name) $o->load($block_name, $edit);
}
return $o;
}
}
\ No newline at end of file
......@@ -4,7 +4,9 @@ class FrxBlockEditor {
public $block_name;
public $modified;
public $provider;
public $cache = FALSE; // Turn on caching of parameter to facilitate block caching.
private $teng;
public $edit;
private $new_block = array(
'type' => 'sql',
'file' => '',
......@@ -13,9 +15,11 @@ class FrxBlockEditor {
'info' => array(),
);
public function __construct($block_name = '') {
public function __construct($block_name = '', $edit = TRUE) {
$this->edit = $edit;
if ($block_name) {
$this->load($block_name);
$this->load($block_name, $edit);
}
$this->teng = Frx::SyntaxEngine(FRX_SQL_TOKEN, ':');
}
......@@ -24,12 +28,17 @@ class FrxBlockEditor {
* Block loader method.
* @param $block_name
*/
public function load($block_name) {
public function load($block_name, $edit=TRUE) {
$block_name = str_replace('.', '/', $block_name);
@list($provider, $path) = explode('/', $block_name, 2);
$this->provider = $provider;
$this->block_name = $block_name;
if (!isset($_SESSION['forena_query_editor'][$block_name])) {
if (isset($_SESSION['forena_query_editor'][$block_name]) && $edit) {
$block = $_SESSION['forena_query_editor'][$block_name];
drupal_set_message(t('All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard your changes.'), 'warning', FALSE);
$this->modified = TRUE;
}
else {
$block = Frx::RepoMan()->loadBlock($block_name);
$this->modified = FALSE;
if (!$block) {
......@@ -37,11 +46,6 @@ class FrxBlockEditor {
$this->update($this->block);
}
}
else {
$block = $_SESSION['forena_query_editor'][$block_name];
drupal_set_message(t('All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard your changes.'), 'warning', FALSE);
$this->modified = TRUE;
}
$this->block = $block;
return $block;
}
......@@ -108,55 +112,26 @@ class FrxBlockEditor {
$this->update($this->block);
}
public function preview($parms = array()) {
$preview = '';
FrxReportGenerator::instance()->alter_parameters('', $parms);
$block = $this->block;
if ($block['type'] == 'sql') {
$sql = $block['file'];
$data = Frx::RepoMan()->sqlData($this->provider, $sql, $parms);
}
else {
Frx::Data()->push($parms, 'parm');
Frx::RepoMan()->data($this->block_name);
Frx::Data()->pop();
}
// Generate the template
$t = Frx::Template('FrxTable');
$config = array('class' => 'dataTable', 'id' => 'preview-data');
if ($data && $t) {
$t->generate($data, $config);
$fields = $t->columns;
if ($fields) $fields = array_combine($fields, $fields);
if ($fields) {
$report = $t->asXML();
$rpt = new FrxReport($report, $data);
$preview = $rpt->render('web', FALSE);
}
else {
if (is_object($data) && method_exists($data, 'asXML')) {
$preview = '<pre>' . htmlspecialchars($data->asXML()) . '</pre>';
}
else {
$preview = '<pre>' .htmlspecialchars(print_r($data,1)) .'</pre>';
}
}
}
return $preview;
}
/**
* Get data and working cache.
* @param unknown $parms
* @return Ambigous <unknown, string, NULL>
*/
public function data($parms = array()) {
if ($parms) {
// Merge in current_context
$data = array_merge(Frx::Data()->currentContextArray(), $data);
$parms = array_merge(Frx::Data()->currentContextArray(), $parms);
$id = str_replace('/', '-', $this->block_name) . '-parm';
Frx::Data()->push($data, $id);
Frx::Data()->push($parms, $id);
}
if ($this->edit) {
$xml = Frx::RepoMan()->sqlData($this->provider, $this->block['file'], $parms);
}
else {
$xml = Frx::RepoMan()->data($this->block_name);
}
$xml = Frx::RepoMan()->data($this->block_name, NULL);
if ($parms) Frx::Data()->pop();
return $xml;
......
......@@ -42,18 +42,21 @@ class FrxData extends FrxContext {
return $data;
}
$parms = array();
$ret = array();
if (is_object($data)) {
// Get attributes
$data = get_object_vars($data);
$ret = get_object_vars($data);
if (method_exists($data, 'attributes')) {
foreach ($data->attributes() as $key => $value) {
$data[$key] = (string)$value;
$ret[$key] = (string)$value;
}
}
return $data;
}
else {
$ret = (array)$data;
}
return $ret;
}
......
......@@ -242,7 +242,7 @@ class FrxDataSource{
}
public function debug($msg='', $log='') {
FrxReportGenerator::instance()->app->debug($msg, $log);
Frx::debug($msg, $log);
}
public function error($msg='', $log='') {
......
......@@ -128,35 +128,9 @@ class FrxDrupalApplication {
}
}
/**
* General wrapper procedure for reporting erros
*
* @param string $short_message Message that will be displayed to the users
* @param string $log Message that will be recorded in the logs.
*/
function error($short_message='', $log='') {
if ($short_message) {
drupal_set_message(check_markup($short_message), 'error');
}
if ($log) {
watchdog('forena', $log, NULL, WATCHDOG_ERROR);
}
}
/**
* Debug handler
* Enter description here ...
* @param unknown_type $short_message
* @param unknown_type $log
*/
function debug($short_message='', $log='') {
if ($log) {
watchdog('forena debug', $log, NULL);
}
if ($short_message) {
drupal_set_message(check_markup($short_message));
}
}
/**
* Builds a global array of available controls
......
......@@ -9,6 +9,7 @@ require_once 'FrxReport.inc';
*
*/
class FrxEditor {
public $edit = TRUE; // Indicates we are running in edit mode.
public $dom;
public $document_root;
public $simplexml;
......@@ -18,6 +19,8 @@ class FrxEditor {
public $cache;
public $frxReport;
public $desc;
public $parms = array(); // Current editor parameters.
public $access = TRUE; // The user has access to the report.
public $doc_prefix = '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY nbsp "&#160;">
......@@ -28,18 +31,21 @@ class FrxEditor {
/**
* Create initial FRX report
* Construct the editor
* Enter description here ...
* @param unknown_type $xml_string
* @param unknown_type $report_name name of report to load
*/
public function __construct($report_name) {
public function __construct($report_name, $edit = TRUE) {
$this->dom = new DOMDocument('1.0', 'UTF-8');
$this->edit = $edit;
$dom = $this->dom;
$dom->formatOutput = TRUE;
$dom->preserveWhiteSpace = TRUE;
$this->load($report_name);
$this->frxReport = new FrxReport();
$this->frxReport->setReport($this->dom);
$cache = forena_load_cache($this->frxReport->rpt_xml);
if (isset($cache['access'])) $this->access = forena_check_all_access($cache['access']);
}
/**
......@@ -77,14 +83,14 @@ class FrxEditor {
* @param unknown_type $report_name
* @return string
*/
public function load($report_name) {
public function load($report_name, $edit=TRUE) {
$this->desc = Frx::Menu()->parseURL($report_name);
$r_text='';
$dom = $this->dom;
$this->report_name = $report_name = $this->desc['name'];
// Load the latest copy of the report editor
if ($report_name) {
if (isset($_SESSION['forena_report_editor'][$report_name])) {
if (isset($_SESSION['forena_report_editor'][$report_name]) && $edit) {
$r_text = $_SESSION['forena_report_editor'][$report_name];
drupal_set_message(t('All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard your changes.'), 'warning', FALSE);
}
......@@ -342,13 +348,17 @@ class FrxEditor {
'value');
}
public function addParameter($parm) {
$parms= array();
$parms[$parm['id']] = $parm;
$this->setFrxHeader('parameters', 'parm',
$parms,
array('id', 'label', 'require', 'desc', 'data_source', 'data_field', 'type'),
'value');
public function addParameters($parms_to_add) {
$parms_to_add = (array)$parms_to_add;
foreach ($parms_to_add as $parm) {
$parms= array();
$parms[$parm] = array('id' => $parm );
$this->setFrxHeader('parameters', 'parm',
$parms,
array('id', 'label', 'require', 'desc', 'data_source', 'data_field', 'type'),
'value');
}
}
/**
......@@ -647,6 +657,7 @@ class FrxEditor {
* getConfig method on the block.
*/
public function scrapeBlockConfig($id, &$config) {
$template_class = "FrxTable";
$path = "//*[@id='$id']";
$nodes = $this->simplexml->xpath($path);
if ($nodes) ( $node = dom_import_simplexml($nodes[0]));
......@@ -670,11 +681,8 @@ class FrxEditor {
$c->initReportNode($node, $$this->frxReport);
$config = array_merge($config,$c->getConfig());
}
return $template_class;
}
else {
return 'FrxTable';
}
return $template_class;
}
......@@ -699,7 +707,7 @@ class FrxEditor {
$class = $node->getAttribute("class");
$config['block'] = $block_name;
$data= Frx::BlockEditor($block_name)->data();
$data= Frx::BlockEditor($block_name)->data($this->parms);
$c = Frx::Template($template_class);
if ($c) {
$c->initReportNode($node, $this->frxReport);
......@@ -713,6 +721,10 @@ class FrxEditor {
}
}
public function setEditorParms($parms) {
$this->parms = $parms;
}
/**
* Add a data blcok
* @param unknown $block
......@@ -733,7 +745,10 @@ class FrxEditor {
}
$config['block'] = $block_name;
$data= Frx::BlockEditor($block_name)->data();
$b = Frx::BlockEditor($block_name, $this->frxReport->block_edit_mode);
$data= $b->data($this->parms);
$this->addParameters($b->tokens());
$this->frxReport->setReport($this->dom);
$c = Frx::Template($template_class);
if ($c) {
$c->initReportNode($node, $this->frxReport);
......@@ -745,27 +760,116 @@ class FrxEditor {
return $this;
}
public function preview() {
public function preview($parms = array()) {
$r = $this->frxReport;
if(strpos($this->report_name, '__') !== 0) $r->preview_mode = TRUE;
return $this->report($parms, TRUE, TRUE);
}
/**
* Load and render a report based on a drupal path.
* In this function the arglist is used to get the full path to the report.
* Pass parameters or NULL to use get /post parameters.
*
* @return unknown
*/
function report($parms = array(), $print = FALSE, $no_cache=FALSE) {
global $user;
$content = array();
$format = $this->desc['format'];
$r = $this->frxReport;
// Determine the data to get.
if (!$parms) {
$parms = array_merge($_GET, $_POST);
unset($parms['q']);
}
else $parms = (array)$parms;
// Allow other modules to alter paramters.
$this->alterParameters($parms);
//check for default parameters
$r->processParameters();
$r->processParameters($parms);
Frx::Skin()->load($r->skin);
Frx::Skin()->loadSkinFiles('');
return $r->render('web');
Frx::Skin()->loadSkinFiles($this->report_name);
$cached_data = FALSE;
$cache = array();
/**
* Allow modules to alter the parameters of a report.
* @param unknown_type $report_name
* @param unknown_type $parms
*/
// Set parameters
Frx::Data()->push($parms, 'parm');
// Check for cache data
if ($r->cache) {
$cid = 'forena:report:' . $name . ':' . drupal_http_build_query($parms);
if (@$r->cache['per_user'] && $user) $cid .= ':' . $user->uid;
if (@$r->cache['per_doctype']) @$cid .= ':' . $format;
$cache = cache_get($cid, 'cache');
if (!$cache || (isset($r->cache['duration']) && $cache->expire < time()) || $no_cache) {
$r->render($format);
$time = null;
if (isset($r->cache['duration'])) {
try {
$time = @new DateTime($r->cache['duration']);
}
catch (Exception $e) {
drupal_set_message('Invalid Cache Duration', 'error', TRUE);
}
if ($time) $time = $time->getTimeStamp();
}
if (!$time) {
$time = CACHE_PERMANENT;
}
$r->cache['content'] = $r->html;
cache_set($cid, $r->cache, 'cache', $time);
}
else {
$r->html = $r->cache['content'];
}
}
else {
$r->render($format);
}
Frx::Data()->pop();
$content = array(
'parameter_form' => $r->parameters_form,
'links' => $this->documentLinks(),
'content' => array('#markup' => $r->html),
);
$o = Frx::Document($format);
if ($o) {
$output = $o->render($r, $format, array());
if ($print) {
$printed = $o->output($output);
}
else {
$printed = FALSE;
}
if (!$printed) {
return $content;
}
}
}
public function editLinks($frx, $id='') {
public function editLinks($frx, $id='', $context = array()) {
$o = '';
if ($frx['block']) {
$block_name = (string)$frx['block'];
$block_link = str_replace('/', '.', $block_name);
$report_name = str_replace('/', '.' , $this->report_name);
//$b=Frx::BlockEditor($block_name)->block;
$options = array();
if ($context) $options['query'] = $context;
$o = '<div class="forena-edit-links">' . l($block_name, "reports/$report_name/edit/data/$block_link/$id" ) . "</div>";
$o = '<div class="forena-edit-links">' . l($block_name, "reports/$report_name/edit/data/$block_link/$id", $options ) . "</div>";
}
return $o;
......@@ -798,4 +902,26 @@ class FrxEditor {
}
return $templates;
}
public function documentLinks() {
$doctypes = array_keys(Frx::documentTypes());
$links = array();
$r = $this->frxReport;
foreach ($doctypes as $ext) {
if (array_search($ext, $r->formats) !== FALSE) {
$links[] = array('title' => $ext, 'href' => str_replace('/', '.', $this->report_name) . ".$ext");
}
}
if ($links) return array('#theme' => $links, '#links' => $links);
return '';
}
/**
* Allow modules to alter the parameters of a report.
* @param unknown_type $report_name
* @param unknown_type $parms
*/
function alterParameters(&$parms) {
drupal_alter('forena_parameters', $this->report_name, $parms );
}
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ require_once('FrxSyntaxEngine.inc');
require_once('renderers/FrxRenderer.inc');
class FrxReport {
public $block_edit_mode = false;
public $blocks_loaded;
public $rpt_xml;
public $fields;
......@@ -151,19 +152,16 @@ class FrxReport {
* @return unknown_type
*/
public function getData($block, $clause='', $id='', $data_uri='') {
$data = array();
if ($data_uri) {
parse_str($data_uri, $data);
if (is_array($data)) foreach ($data as $key => $value) {
$data[$key] = $this->teng->replace($value, TRUE);
}
// Merge in current_context
$data = array_merge(Frx::Data()->currentContextArray(), $data);
$id .= '-parm';
Frx::Data()->push($data, $id);
}
$xml = Frx::RepoMan()->data($block, NULL);
$xml = Frx::BlockEditor($block, $this->block_edit_mode)->data($data);
//$xml = Frx::RepoMan()->data($block, NULL);
if ($data_uri) Frx::Data()->pop();
if ($xml) {
......@@ -172,6 +170,17 @@ class FrxReport {
return $xml;
}
/**
* Collapse the parameters if the data is loaded.
*/
public function collapseParameters() {
if (is_array($this->parameters_form) && $this->parameters_form) {
$form = $this->parameters_form;
if (isset($form['params']) && @$forms['params']['#collapsible']) {
$this->parameters_form['params']['#collapsed'] = !$this->blocks_loaded;
}
}
}
/**
* Render the report
......@@ -182,37 +191,27 @@ class FrxReport {
// Only push the parameter conte
Frx::Data()->push($this->parms, 'parm');
// Find the Body of the report.
$this->format = $format;
$dom = $this->dom;
$body = $dom->getElementsByTagName('body')->item(0);
// Render the rport.
$o='';
if (!$this->missing_parms || $this->rpt_xml->xpath('//*[@frx:renderer="FrxParameterForm"]')) {
if ($cache_data && $cache_data['content']) {
$o .= $cache_data['content'];
}
else {
$c = Frx::Controls('FrxRenderer');
$c->initReportNode($body, $this);
$o .= $c->renderChildren($body);
}
}
$this->parametersForm(array('collapsible' => TRUE));
$c = Frx::Controls('FrxRenderer');
$c->initReportNode($body, $this);
if (!$this->missing_parms) $o .= $c->renderChildren($body);
$this->collapseParameters();
$this->html = $o;
// Default in dynamic title from head.
if ($this->frx_title) {
$title = check_plain($this->teng->replace($this->frx_title));
if ($title) $title = $this->title = $title;
}
if ($render_form && !$this->rpt_xml->xpath('//*[@frx:renderer="FrxParameterForm"]') && $format=='web') {
$variables = array('collapse' => $this->blocks_loaded);
$this->parameters_form = $form = $this->parametersForm($variables);
}
Frx::Data()->pop();
if ($this->cache) {
$this->cache['content'] = $this->html;
}
return $this->html;
}
......@@ -496,8 +495,13 @@ class FrxReport {
* @param $parms Array of parameters.
* @return boolean indicating whether the required parameters are present.
*/
public function processParameters() {
$parms = $this->parms;
public function processParameters($parms=NULL) {
if ($parms==NULL) {
$parms = $this->parms;
}