Commit 175834fd authored by metzlerd's avatar metzlerd
Browse files

Data plugin refactor.

parent b64846cf
......@@ -99,4 +99,34 @@ class Frx {
return $o;
}
/**
* 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.
*/
public static 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
*/
public static function debug($short_message='', $log='') {
if ($log) {
watchdog('forena debug', $log, NULL);
}
if ($short_message) {
drupal_set_message(check_markup($short_message));
}
}
}
\ No newline at end of file
......@@ -13,6 +13,7 @@ class FrxDataSource{
public $comment_prefix;
public $comment_suffix;
public $block_ext;
public $types;
protected $te;
public function __construct($conf, $repos_path) {
$this->conf = $conf;
......@@ -44,51 +45,60 @@ class FrxDataSource{
return user_access('access content');
}
}
/**
* Default block load
* Loads the data block based on the block name from the file system. The classes that
* are derived from this will set the block_ext property, which in most cases is .sql but
* might be something different. The load of the block file should return data, access and
* probably parameters to.
* @param unknown_type $block_name
* @return unknown
* Load blcok data from filesystem
* @param $block_name
*/
public function load_block($block_name, $clause='') {
$filename = $this->block_path . '/' . $block_name . '.' . $this->block_ext;
$contents = FrxReportGenerator::instance()->load_block_file($filename);
if ($this->block_ext == 'sql') {
$block = $this->parseSQLFile($contents);
function loadBlock($block_name) {
$block = array();
$base_file = $this->block_path . '/' . $block_name;
if (file_exists($base_file . '.sql')) {
$contents = file_get_contents($base_file . '.sql');
$block = $this->parseSQLFile($contents);
$block['type'] = 'sql';
$block['tokens'] = $this->tokens($block['source']);
}
else {
$block = $this->parseXMLFile($contents);
elseif (file_exists($base_file . '.xml')) {
$contents = file_get_contents($base_file . '.xml');
$block = $this->parseXMLFile($contents);
$block['type'] = 'xml';
$block['tokens'] = $this->tokens($block['source']);
}
// If we have a regular expression token parser, then get the tokens out of the block.
elseif (file_exists($base_file . '.inc')) {
$parts = pathinfo($base_file . '.inc');
@list($class, $method) = explode('.', $parts['filename']);
$inc = $base_file . '.inc';
require_once $inc;
if (class_exists($class)) {
$o = new $class();
$block['type'] = 'php';
$block['access'] = @$o->access;
$block['object'] = $o;
$block['method'] = $method;
if (method_exists($o, 'tokens' )) {
$block['tokens'] = $o->tokens();
}
}
}
return $block;
}
/**
* Load tokens from block source
*/
public function tokens($soucre) {
$tokens = array();
// If we have a regular expression token parser, then get the tokens out of the block.
if ($this->te) {
$tokens = @$this->te->tokens($block['source']);
$tokens = @$this->te->tokens($source);
$tokens = array_diff($tokens, array('current_user'));
//check tokens in the where clause
if ($clause) {
$clause_tokens = $this->te->tokens($clause);
//drupal_set_message("clause tokens: ". print_r($clause_tokens, 1));
$temp = array();
$temp = array_merge($tokens, $clause_tokens);
//check for duplicates in block tokens
if ($clause_tokens) foreach ($clause_tokens as $ct) {
if (!isset($temp[$ct])) {
array_push($tokens, $ct);
}
}
}
$block['tokens'] = $tokens;
}
return $block;
return $tokens;
}
/**
......@@ -214,4 +224,34 @@ class FrxDataSource{
return array('access' => $access, 'source' => $data);
}
/**
* Dummy method for returning sql data
* @param unknown_type $parameters
*/
public function sqlData($parameters) {
return '';
}
/**
* Implement static XML functioin
* @param $source XML Source data from block load
* @param $parm_data Parameter data
*/
public function xmlData($source, $parm_data='') {
$xml ='';
try {
$xmlData = $block['source'];
$xml = new SimpleXMLElement($xmlData);
} catch (Exception $e) {
$this->error("Error processing xml\n", $e->getMessage() . "\n" . $xmlData);
}
return $xml;
}
public function phpData($method, $paremeters) {
$xml = '';
return $xml;
}
}
<?php
/**
*
* Enter description here ...
* @author davidmetzler
*
*/
class FrxRepoMan {
public $repositories;
/**
* Loads all of the include files that
*/
private function define_plugins( $class='') {
static $plugins = '';
if (!$plugins) {
$plugins = array();
foreach (module_list() as $module) {
$function = $module . '_forena_plugins';
if (function_exists($function)) {
$returned_plugins = $function();
if ($returned_plugins) foreach ((array)$returned_plugins as $p) {
$p['module'] = $module;
$p['file'] = drupal_get_path('module' , $p['module']) . '/' . $p['file'];
$plugins[]=$p;
}
}
}
}
foreach ($plugins as $p) {
if (($class=='' || $class==$p['class'])) {
if ($p['file'] ) {
include_once( trim($p['file'], '/'));
}
}
}
}
//Determine data sources.
public function __construct() {
global $_forena_repositories;
// Empty repository so we need to initialize
// Build the default sample one
$repos = array();
// Load the repository list from the global settings.php file.
if ($_forena_repositories) {
$repos = $_forena_repositories;
}
// Overide difinitions of the sample and drupal repositories.
$path = drupal_get_path('module', 'forena');
$repos['forena_help'] = array(
'path' => $path .'/repos/forena_help',
'title' => 'Forena Help Reports',
);
$repos['drupal'] = array(
'path' => $path . '/repos/drupal',
'title' => 'Drupal Reports',
);
$repos['sampledb'] = array(
'path' => $path . '/repos/sample',
'title' => 'Sample DB Repository'
);
// Retrieve the repositories defined in the database;
$results = db_query('SELECT * FROM {forena_repositories}');
foreach ($results as $r) {
if ($r->config) {
$new_r = unserialize($r->config);
}
else {
$new_r = array();
}
$r_name = $r->repository;
if (is_array(@$repos[$r_name])) {
$new_r = array_merge($new_r, $repos[$r_name]);
}
else {
$new_r['source'] = 'user';
}
$new_r ['title'] = $r->title;
$new_r ['enabled'] = $r->enabled;
$repos[$r_name] = $new_r;
}
drupal_alter('forena_repos', $repos);
if ($_forena_repositories) {
array_merge($repos, $_forena_repositories);
}
$this->repositories = $repos;
}
/**
* Load repository
* @param $name Name of the repository
*/
public function repository($name) {
// Now determine if the object exists
if (isset($this->repositories[$name])) {
if (@!is_object($this->repositories[$name]['data'])) {
$this->load_repository($this->repositories[$name]);
}
return $this->repositories[$name]['data'];
}
else {
Frx::error('Undefined repository' . $name, "Undefined Repository: $name ");
}
}
// Putting this in a function to sandbox the repository settings
public function load_repository(&$repo) {
// First determine if the class file exisits
$path = @$repo['path'];
$conf = array();
if (file_exists($path . '/settings.php')) {
// Override with repository specific data
include($path . '/settings.php');
}
$repo = array_merge($conf, $repo);
if (!isset($repos['data'])||!is_object($repo['data'])) $repo['data'] = $this->load_provider($repo, $path);
}
/**
* Load the data provider class based on the class name.
*
* @param string $name
* @return object The data provider object
*/
public function load_provider($conf, $repo_path) {
@$name = isset($conf['data provider'])? $conf['data provider'] : $conf['data_engine'];
$this->define_plugins();
// Instantiate the path
if (class_exists($name)) {
$o = new $name($conf, $repo_path);
return $o;
}
else {
Frx::error('Data provider not found for '. $conf['title']);
}
}
/**
* Extract the data by running a block
*
* @param unknown_type $data_block
* @param unknown_type $parameters
* @param string $clause order / where cause
* @return unknown
*/
function data($data_block, $parameters=array()) {
list($provider, $block_name) = explode('/', $data_block, 2);
$repos = @$this->repositories[$provider];
if (isset($repos['enabled']) && !$repos['enabled']) {
return '';
}
//Populate user callback.
if (isset($repos['user callback'])) {
$user_fn = $repos['user callback'];
if (is_callable($user_fn)) {
$current_user = $user_fn();
Frx::Data()->setValue('current_user', $current_user);
}
}
//Execute the provider
$o = $this->repository($provider);
$xml = '';
if ($o) {
$access = TRUE;
$block = $o->loadBlock($block_name);
$right = $block['access'];
if ($block && $o->access($right)) {
switch ($block['type']) {
case 'sql':
$xml = $o->sqlData($block['source'], $parameters);
break;
case 'file':
$xml = $o->xmlData($block['source'], $parameters);
break;
case 'class':
break;
}
}
return $xml;
}
else {
return '';
}
}
}
\ No newline at end of file
......@@ -123,7 +123,7 @@ class FrxReport {
Frx::Data()->push($data, $id);
}
$xml = FrxReportGenerator::instance()->invoke_data_provider($block, null, $clause);
$xml = Frx::RepoMan()->data($block, null);
if ($data_uri) Frx::Data()->pop();
......
......@@ -35,102 +35,6 @@ class FrxReportGenerator {
$app = $this->app = new $application_class();
}
/**
* Get name from argument 1 or alterntaively from a file name
*
* @param unknown_type $name
*/
public function report_desc($name='') {
$app = $this->app;
// Get defined document types
$doctypes = $this->supported_doctypes();
$parts = explode('.', $name);
$name ='';
if ($parts) foreach ($parts as $part) {
if (!isset($doctypes[$part])) {
$name .= '/' . $part;
}
else {
$desc['format'] = $part;
}
}
$desc['name'] = trim($name, '/');
$report_path = $app->configuration('report_repos');
@list ($dir, $name_part) = explode('/', $name_part, -2);
if (!$name_part) $dir = '';
$desc['directory'] = $report_path . '/' . $dir;
$desc['filename'] = $report_path . '/' . trim($name, ' /') . '.frx';
$desc['link'] = 'reports/' . trim(str_replace('/' , '.', $name), '.');
$desc['exists'] = file_exists($desc['filename']);
return $desc;
}
/**
* Determines which css files need to be loaded.
*
* @param array $desc Report descriptor from forena_rport_desc
* @param string $form The report "form" to be used. From the report
* @param string $format Document format that will be used for the report.
* @return array A list of css files that should be applied to the report.
*/
function report_css($desc, $form, $format = '') {
$css_files = array();
// First check for the form file
$path = $this->app->configuration('report_repos');
if (file_exists($path . '/' . $form . '.css')) {
$css_files[] = $path . '/' . $form . '.css';
}
if ($format && file_exists($path . '/' . $form . '-' . $format . '.css')) {
$css_files[] = $path . '/' . $form . '-' . $format . '.css';
}
// Now check for a report specific file
$base_file = $path . '/' . $desc['name'];
if ($format && file_exists($base_file . '-' . $format . '.css')) {
$css_files[] = $base_file . '-' . $format . '.css';
}
elseif (file_exists($base_file . '.css')) {
$css_files[] = $base_file . '.css';
}
return $css_files;
}
/**
* Determines which js files need to be loaded.
*
* @param array $desc Report descriptor from forena_rport_desc
* @param string $form The report "form" to be used. From the report
* @param string $format Document format that will be used for the report.
* @return array A list of css files that should be applied to the report.
*/
function report_js($desc, $form, $format = '') {
$js_files = array();
// First check for the form file
$path = $this->app->configuration('report_repos');
if (file_exists($path . '/' . $form . '.js')) {
$js_files[] = $path . '/' . $form . '.js';
}
if ($format && file_exists($path . '/' . $form . '-' . $format . '.js')) {
$js_files[] = $path . '/' . $form . '-' . $format . '.js';
}
// Now check for a report specific file
$base_file = $path . '/' . $desc['name'];
if ($format && file_exists($base_file . '-' . $format . '.js')) {
$js_files[] = $base_file . '-' . $format . '.js';
}
elseif (file_exists($base_file . '.js')) {
$js_files[] = $base_file . '.js';
}
return $js_files;
}
/**
* Clear session data because we want to reload.
*/
......@@ -158,7 +62,7 @@ class FrxReportGenerator {
// Get the block from the repository
$frxData = Frx::Data();
$frxData->push(array(), 'frx-block-access');
$data = $this->invoke_data_provider($block, array(), NULL);
$data = Frx::RepoMan()->data($block, array());
$frxData->pop();
if ($data) {
if (!$path) {
......@@ -263,38 +167,6 @@ class FrxReportGenerator {
return $this->invoke_data_provider($block_name, $parms);
}
/**
* Extract the data by running a block
*
* @param unknown_type $data_block
* @param unknown_type $parameters
* @param string $clause order / where cause
* @return unknown
*/
function invoke_data_provider($data_block, $parameters=array(), $clause='') {
list($provider, $block) = explode('/', $data_block, 2);
// Get the data
$repos = $this->repository($provider);
if (isset($repos['enabled']) && !$repos['enabled']) {
return '';
}
if (isset($repos['user callback'])) {
$user_fn = $repos['user callback'];
if (is_callable($user_fn)) {
$current_user = $user_fn();
Frx::Data()->setValue('current_user', $current_user);
}
}
if ($repos['data']) {
$provider = $repos['data'];
$access = TRUE;
if (method_exists($provider, 'data')) {
$xml = $provider->data($block, $parameters, $clause);
}
return $xml;
}
}
/**
* Returns an array of information about the data block
* @param $data_block
......@@ -310,7 +182,7 @@ class FrxReportGenerator {
if (isset($repos['data'])) {
$provider = $repos['data'];
if (method_exists($provider, 'load_block')) {
$block_info = $provider->load_block($block, $clause);
$block_info = $provider->loadBlock($block, $clause);
}
return $block_info;
......@@ -437,7 +309,7 @@ function load_block($data_block, $clause='') {
if ($repos['data']) {
$provider = $repos['data'];
if (method_exists($provider, 'load_block')) {
$block_info = $provider->load_block($block, $clause);
$block_info = $provider->loadBlock($block);
}
return $block_info;
......@@ -461,19 +333,6 @@ function load_block($data_block, $clause='') {
return $block_data;
}
/**
* Loads all of the include files that
*/
function define_plugins( $class='') {
$plugins = $this->app->plugins();
foreach ($plugins as $p) {
if (($class=='' || $class==$p['class'])) {
if ($p['file'] ) {
include_once( trim($p['file'], '/'));
}
}
}
}
/**
* returns a list of instances of the control classes
......@@ -707,9 +566,9 @@ function report($name_in, $parms = array(), $print=TRUE) {
* @where_clause: Where clause for data block to be filtered against.
*
*/
function data_block_params($data_block, $field, $label, $params=array(), $clause='') {
function data_block_params($data_block, $field, $label, $params=array()) {
Frx::Data()->push($params);
$xml = $this->invoke_data_provider($data_block, $params, $clause);
$xml = Frx::RepoMan()->data($data_block);
Frx::Data()->pop();
$list = array();
......
......@@ -35,7 +35,7 @@ class FrxSQLQueryBuilder {
* Enter description here ...
*/
public function execute() {
return FrxReportGenerator::instance()->invoke_data_provider($this->block, $this->data, $this->sql());
return Frx::RepoMan()->data($this->block, $this->data, $this->sql());
}
/**
......
......@@ -1640,7 +1640,7 @@ function forena_data_select_block_submit($form, &$form_state) {
//now invoke the data provider with the correct params
Frx::Data()->push($parms, 'parm');
$form_state['storage']['parms'] = $params;
$xml = FrxReportGenerator::instance()->invoke_data_provider($data_block, $parms, $where_clause);
$xml = Frx::RepoMan()->data($data_block, $parms);
if ($xml) {
$form_state['storage']['step'] = 'select_template';
$form_state['storage']['xml'] = $xml->asXML();
......@@ -2007,7 +2007,7 @@ function forena_user_data_blocks($search) {
if (method_exists($o, 'list_blocks')) {
$blocks = $o->list_blocks($search);
foreach ($blocks as $block) {
$block_info = $o->load_block($block);
$block_info = $o->loadBlock($block);
if (method_exists($o, 'access')) {
$allow = $o->access($block_info['access']);
if ($allow) $user_blocks[] = $name . '/' . $block;
......
......@@ -51,7 +51,7 @@ function forena_load_cache($r_xhtml) {
if ($provider && $block_name) {