Commit 93d2e1e7 authored by metzlerd's avatar metzlerd
Browse files

Working save and date/teaser formatting.

parent 78be96ec
<?php
// $Id$
require_once('forena.common.inc');
/**
* @file
* Class that defines default methods for access control in an FrxDataEngine
......
......@@ -4,41 +4,64 @@
* @file
* Basic report engine. Controls the rendering of the report.
*/
define('FRX_NS','urn:FrxReports');
require_once('FrxSyntaxEngine.inc');
class FrxReport {
private $rpt_xml;
public $rpt_xml;
private $cur_data;
private $output;
private $teng;
public $fields;
public $category;
public $access;
public $parameters;
public $options;
public $body;
public function __construct($xhtml, $data=array()) {
$this->teng = new FrxSyntaxEngine(FRX_TOKEN_EXP, '{}', $this);
$this->access = array();
$this->parameters = array();
$this->options = array();
if ($xhtml) {
if (!is_object($xhtml)) {
$this->rpt_xml = new SimpleXMLElement($xhtml);
}
else {
else {
$this->rpt_xml = $xhtml;
}
$this->cur_data = $data;
// Load header data
$rpt_xml = $this->rpt_xml;
$this->body = $rpt_xml->body;
if ($rpt_xml->head) {
$this->title = (string)$rpt_xml->head->title;
foreach ($rpt_xml->head->children('urn:FrxReports') as $name => $node) {
foreach ($rpt_xml->head->children(FRX_NS) as $name => $node) {
switch ($name) {
case 'fields':
$this->fields = $node;
break;
case 'category':
case 'fields':
$this->fields = $node;
break;
case 'category':
$this->category = (string)$node;
break;
case 'options':
foreach ($node->attributes() as $key => $value) {
$this->options[$key] = (string)$value;
}
break;
case 'parameters':
foreach ($node->children(FRX_NS) as $key => $node) {
$parm = array();
foreach ($node->attributes() as $akey => $attr) {
$parm[$akey] = (string)$attr;
}
$parm['value']= (string)$node;
$this->parameters[$key] = $parm;
}
break;
}
}
}
......@@ -51,30 +74,34 @@ class FrxReport {
* @return unknown_type
*/
private function get_data($block) {
//@TODO: Merge xml data parameters into the report paramters
//@TODO: Merge xml data parameters into the report paramters
$this->cur_data = forena_invoke_data_engine($block, $this->cur_data);
}
private function process_frx_attributes(SimpleXMLElement $node) {
$attrs = $node->attributes('urn:FrxReports');
$attrs = $node->attributes(FRX_NS);
if ($attrs) foreach ($attrs as $key => $value) {
switch ($key) {
case "block":
$this->get_data((string)$value);
break;
}
}
}
/**
* Recursive report renderer
* Walks the nodes renering the report.
* Walks the nodes rendering the report.
*/
public function render_section(SimpleXMLElement $node) {
//drupal_set_message('Rendering Section '. $node->getName());
$cur_data = $this->cur_data;
$elements = count($node->xpath('*'));
$frx = $node->attributes('urn:FrxReports');
$frx = $node->attributes(FRX_NS);
// Test to see if we have any nodes that are contains data url
if ($node->xpath('*//@frx:*') || $frx) {
$attrs = $node->attributes();
......@@ -84,19 +111,18 @@ class FrxReport {
$attr_text = ' '. $key .'="'. (string)$value .'"';
}
$frx = $node->attributes('urn:FrxReports');
if ((string)$frx['foreach'] ) {
$frx = $node->attributes(FRX_NS);
if ((string)$frx['foreach'] ) {
// Save xml
$path = (string)$frx['foreach'];
$data = $this->cur_data;
$path = (string)$frx['foreach'];
$data = $this->cur_data;
if ($data) $nodes = $data->xpath($path);
if ($nodes) foreach ($nodes as $x) {
$this->cur_data = $x;
$o .= $this->teng->replace('<'. $tag . $attr_text .'>', $cur_data);
$o .= $this->teng->replace('<'. $tag . $attr_text .'>', $cur_data);
foreach ($node->children() as $child) {
$o .= $this->render_section($child);
}
......@@ -106,21 +132,22 @@ class FrxReport {
$this->cur_data = $data;
}
else {
$o .= $this->teng->replace('<'. $tag . $attr_text .'>', $this->cur_data);
foreach ($node->children() as $child) {
$o .= $this->render_section($child);
$o .= $this->render_section($child);
}
$o .= '</'. $tag .'>';
}
}
else {
$tag = $node->getName();
// We can render so lets do it.
$text = $node->asXML();
$text = $node->asXML();
$o .= $this->teng->replace($text, $this->cur_data);
}
$this->cur_data = $cur_data;
$this->cur_data = $cur_data;
return $o;
}
......@@ -164,13 +191,7 @@ class FrxReport {
}
if ($format) {
forena_define_plugins('formatter', $format);
if (class_exists($format)) {
$f = new $format();
if (method_exists(f, 'format')) {
$f->format($value, $format_str);
}
}
$value = forena_format_data($value,$format,$format_str);
}
......
......@@ -35,20 +35,29 @@ class FrxSyntaxEngine {
*/
protected function get_value($data, $key, $raw=FALSE) {
$retvar = '';
if (is_array($data)) {
$retvar = $data[$key];
}
elseif (is_object($data)) {
$rows = $data->xpath($key);
if ($rows) $x = $rows[0];
if ($x) $retvar = $x->asXML();
if ($retvar) {
// Find the end of the first tag.
//print $root_tag;
$p = strpos($retvar, '>');
$retvar = substr_replace($retvar, ' ', 0, $p+1);
$p = strrpos($retvar, '<', -1);
$retvar = substr_replace($retvar, '', $p, strlen($retvar) - $p);
$retvar = substr_replace($retvar, '', $p, strlen($retvar) - $p);
}
}
// Call the formatter object if neccessary
......@@ -68,7 +77,7 @@ class FrxSyntaxEngine {
*/
public function replace($text, $data, $raw=FALSE) {
$match=array();
$o_text = $text;
$o_text = $text;
if (preg_match_all($this->tpattern, $o_text, $match)) {
//list($params) = $match[1];
$i=0;
......@@ -76,7 +85,7 @@ class FrxSyntaxEngine {
foreach ($match[0] as $match_num => $token) {
$path = trim($token, $this->trim_chars);
$value = $this->get_value($data, $path, $raw);
$text = str_replace($token, $value, $text);
$text = str_replace($token, $value, $text);
}
}
return $text;
......
......@@ -11,14 +11,19 @@ require_once('forena.common.inc');
* @param string $name File name to save report to
* @param unknown_type $data
*/
function forena_save_report($data, $report, $save_file = FALSE) {
static $save_count=0;
if ($report && !is_object($report)) $report = new SimpleXMLElement($report);
function forena_save_report($report_name, $report, $save_file = FALSE) {
static $save_count=0;
if ($report && !is_object($report)) $report = new SimpleXMLElement($report);
$report_path = forena_report_path();
$r = new FrxReport($report);
$data['title'] = $r->title;
$data['category'] = $r->category;
$data['options'] = $r->options;
$data['name'] = $report_name;
//@TODO: Clean up filename to make sure
$name = $data['name'];
$filepath = $report_path .'/'. $data['name'] .'.frx';
$filepath = $report_path .'/'. $report_name .'.frx';
// If we need to save this to the file system
if ($save_file) {
// Serialize the report for saving
......@@ -33,46 +38,44 @@ function forena_save_report($data, $report, $save_file = FALSE) {
}
}
// Get the security caches from the reports
// Get the security caches from the reports
if ($report) $cache = forena_load_cache($report); else $cache='';
if ($cache) $rpt_cache = serialize($cache);
//drupal_set_message('saving'.$name. print_r($cache,1));
// Set default interpretations of data
$data['enabled'] = $data['enabled'] ? 1 : 0;
if (!$data['category']) $data['category'] = 'All';
$data['hidden'] = ($data['hidden'] && $data['hidden']!='N' && $data['hidden']!='0') ? 1:0;
$data['hidden'] = ($data['options']['hidden'] && $data['optioins']['hidden']!='N' && $data['options']['hidden']!='0') ? 1:0;
// Save to the Database
if (file_exists($filepath)) {
$result = db_query("SELECT report_name FROM {forena_reports} WHERE report_name='%s'", $name);
if ($rpt = db_fetch_object($result)) {
db_query("UPDATE {forena_reports} SET title='%s', category='%s', repository='%s', access='%s'".
//drupal_set_message('updating '.$name. print_r($rpt,1));
db_query("UPDATE {forena_reports} SET title='%s', category='%s'".
", hidden='%s', cache='%s' WHERE report_name='%s'",
array($data['title'],
$data['category'],
$data['repository'],
$data['access'],
$data['hidden'],
$rpt_cache,
$name ));
}
else {
db_query("INSERT INTO {forena_reports} (report_name, title, category, repository, access, hidden, cache) ".
"VALUES ('%s', '%s', '%s', '%s', '%s', %d, '%s')",
//drupal_set_message('insertnig');
db_query("INSERT INTO {forena_reports} (report_name, title, category, hidden, cache) ".
"VALUES ('%s', '%s', '%s', %d, '%s')",
array($name,
$data['title'],
$data['category'],
$data['repository'],
$data['access'],
$data['hidden'],
$rpt_cache,
));
}
$save_count++;
}
return $save_count;
}
return $save_count;
}
/**
......@@ -98,12 +101,9 @@ function forena_db_sync($subdir='') {
// Load the report
$r = new FrxReport($r_xml);
$data['title'] = $r->title;
$data['category'] = $r->category;
$data['repository'] = $r->repository;
$data['access'] = $r->access;
$data['name'] = $report_name;
$save_count = forena_save_report($data, $r_xml);
$save_count = forena_save_report($report_name, $r_xml);
}
}
elseif (is_dir($src_file)) {
......@@ -203,3 +203,75 @@ function forena_settings_submit($form, &$form_state) {
drupal_set_message('Imported '. $save_count .' forms into the database');
menu_cache_clear();
}
/**
* Form function for the edit report form
* @param $form_state
* @return the form
*/
function forena_edit_form($form_state){
$r = forena_get_report(arg(1));
$form = array();
$title = (string)$r->title;
$category = (string)$r->category;
$body = $r->body->asXML();
$form['head'] = array(
'#type' => 'value',
'#value' => $r->rpt_xml->head,
);
$form['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $title,
);
$form['category'] = array(
'#type' => 'textfield',
'#title' => t('Category'),
'#default_value' => $category,
);
$form['body'] = array(
'#type' => 'textarea',
'#title' => t('Body'),
'#default_value' => $body,
'#rows' => 25,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Save',
);
return $form;
}
/**
* builds a string of the xml document,
* submits it to forena_save_report.
*/
function forena_edit_form_submit($form, &$form_state) {
$values = $form_state['values'];
$h = $values['head'];
$xml = '<html xmlns:frx="urn:FrxReports"><head>';
$xml .= '<title>'. htmlspecialchars($values['title']). '</title>';
$xml .= '<frx:category>'. htmlspecialchars($values['category']). '</frx:category>';
$nodes = $h->xpath('frx:options');
if ($nodes) $xml.=$nodes[0]->asXML();
$nodes = $h->xpath('frx:parameters');
if ($nodes) $xml.=$nodes[0]->asXML();
$nodes = $h->xpath('frx:fields');
if ($nodes) $xml.=$nodes[0]->asXML();
$xml .= '</head>';
$xml .= $form_state['values']['body'];
$xml .= '</html>';
if (forena_save_report(arg(1), $xml, TRUE) == 1){
drupal_set_message('Your report, "'. $values['title']. '", has been saved');
$form_state['redirect']= 'reports/' . arg(1);
}
}
......@@ -33,7 +33,7 @@ function __forena_load_repository(&$repo) {
function __forena_load_engine($conf, $repo_path) {
$name = $conf['data_engine'];
forena_define_plugins('data');
forena_define_plugins();
// Instantiate the path
if (class_exists($name)) {
$o = new $name($conf, $repo_path);
......@@ -84,8 +84,8 @@ function forena_repository($name='') {
}
function forena_load_cache($r_xhtml) {
$blocks = array();
function forena_load_cache($r_xhtml) {
$blocks = array();
if (is_object($r_xhtml)) {
$block_xml = $r_xhtml->xpath('//*[@frx:block]');
// Extract all the blocks and organize by provider
......@@ -131,6 +131,7 @@ function forena_load_cache($r_xhtml) {
function forena_invoke_data_engine($data_block, $parameters=array(), $subquery='') {
list($provider, $block) = explode('/', $data_block, 2);
// Get the data
$repos = forena_repository($provider);
if ($repos['data']) {
......@@ -143,6 +144,79 @@ function forena_invoke_data_engine($data_block, $parameters=array(), $subquery='
}
}
/**
* Load the formatters for all initialized repositories.
*
*/
function forena_get_formatter($fkey) {
// Get all repositories
$repos = forena_repository();
foreach ($repos as $k => $r) {
$engine = $r['data'];
if ($engine && method_exists($engine,'formats')) {
$f = $engine->formats();
if ($f[$fkey] && method_exists($engine, $fkey)) {
// We found an object with the advertised method return it
return $engine;
}
}
}
return $formats;
}
/**
* Accepts the name of a file
*
* Returns a xml object of the file.
*
*/
function forena_get_report($report_name){
if ($report_name) {
$report_path = forena_report_path();
$filename = $report_path . '/'. $report_name . '.frx';
if (file_exists($filename)) {
$r_text = file_get_contents($filename);
try {
$r = new SimpleXMLElement($r_text);
$r = new FrxReport($r);
} catch (Exception $e) {
forena_error('Unable to read report', $e->getMessage());
}
}
return $r;
}
}
/**
* Accepts the name of the html tag, and the string the tag is in.
*
* Returns the string within the html tag name
*
*/
function forena_get_html($tag, $r_text){
$open = strpos($r_text, $tag);
$close = strpos($r_text, '>', $open);
$next = strpos($r_text, '<', $close + 1);
$str = substr($r_text, $close + 1, $next - ($close + 1));
return $str;
}
function forena_format_data($value, $format, $format_str) {
$fo = forena_get_formatter($format);
if ($fo) {
$ret = $fo->$format($value, $format_str);
} else {
$ret = $value;
}
return $ret;
}
/**
* Load a block file form disk and introspect the comments to determine security
* Return a structured array based on this.
......@@ -237,10 +311,10 @@ function forena_plugins() {
/**
* Loads all of the include files that
*/
function forena_define_plugins($type ='', $class='') {
function forena_define_plugins( $class='') {
$plugins = forena_plugins();
foreach ($plugins as $p) {
if ((!$type || $type==$p['type']) && ($class='' || $class=$p['class'])) {
if (($class='' || $class=$p['class'])) {
if ($p['file'] && $p['module']) {
include_once( drupal_get_path('module' , $p['module']) .'/'. trim($p['file'], '/'));
}
......
......@@ -16,8 +16,6 @@ function forena_schema() {
'title' => array('type' => 'varchar', 'length' => 63, 'NOT NULL' => TRUE),
'file_name' => array('type' => 'varchar', 'length' => 255, 'NOT NULL' => TRUE),
'category' => array('type' => 'varchar', 'length' => 255, 'NOT NULL' => FALSE),
'repository' => array('type' => 'varchar', 'length' => 255, 'NOT NULL' => FALSE),
'access' => array('type' => 'varchar', 'length' => 255, 'NOT NULL' => FALSE),
'hidden' => array('type' => 'int', 'NOT NULL' => FALSE, ),
'cache' => array('type' => 'text'),
),
......
......@@ -17,15 +17,30 @@ function forena_menu() {
'file' => 'forena.admin.inc',
);
$path = variable_get('forena_path', 'reports');
$items[$path] = array(
$items['reports/%'] = array(
'page callback' => 'forena_report',
'page arguments' => array(),
'page arguments' => array(1),
'title' => t('Reports'),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['reports/%/view'] = array(
'title' => t('View'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['reports/%/edit'] = array(
'title' => 'Edit',
'page callback' => 'forena_edit_report',
'page arguments' => array(1),
'access arguments' => array('design any report'),
'description' => t('Edit the content of your node'),
'type' => MENU_LOCAL_TASK,
);
$items['forena'] = array(
'page callback' => 'forena_user_reports',
'page arguments' => array(),
......@@ -34,9 +49,16 @@ function forena_menu() {
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
* Calls forena_edit_form
*
*/
function forena_edit_report() {
require_once('forena.admin.inc');
return drupal_get_form('forena_edit_form');
}
/**
* Implementation of hook_perm
......@@ -54,16 +76,6 @@ function forena_perm() {
return $perms;
}
/**
* Test function for white box testing.
*
* @return unknown
*/
function forena_test() {
$output .= 'Forena test page';
return $output;
}
function forena_report() {
$arg_list = func_get_args();
......@@ -71,19 +83,19 @@ function forena_report() {
// Concat argument to function to get a path
$f_path = variable_get('forena_path', 'reports');
foreach ($arg_list as $arg) {
$report_name .= '/'. $arg;
}
$report_name = trim($report_name, '/');
$report_path = forena_report_path();
list($name, $format) = explode('.', $report_name, 2);
foreach ($arg_list as $arg) {
$report_name .= '/'. $arg;
}
$report_name = trim($report_name, '/');
$report_path = forena_report_path();
list($name, $format) = explode('.', $report_name, 2);
if ($name) {
$filename = $report_path . '/'. $name . '.frx';
if (file_exists($filename)) {