FrxDataSource.inc in Forena Reports 7.3
Same filename and directory in other branches
Class that defines default methods for access control in an FrxDataSource
File
FrxDataSource.incView source
<?php
// $Id$
require_once 'forena.common.inc';
/**
* @file
* Class that defines default methods for access control in an FrxDataSource
*
*/
class FrxDataSource {
public $name;
public $conf;
public $block_path;
public $comment_prefix;
public $comment_suffix;
public $block_ext;
public $block_extensions;
public $types;
public $block_name;
protected $te;
public $debug = FALSE;
public function __construct($conf, $repos_path, $name) {
$this->conf = $conf;
$this->comment_prefix = '--';
$this->block_ext = 'sql';
$this->block_path = $repos_path;
$this->app = FrxReportGenerator::instance()->app;
$this->block_extensions = array(
'inc',
'sql',
'xml',
);
$this->name = $name;
$this->debug = @$conf['debug'];
}
/**
* Implements the basic default security check of calling
* an access method.
*
* @param unknown_type $arg
* @return unknown
*/
public function access($arg) {
$f = @$this->conf['access callback'];
if ($f && is_callable($f)) {
return $f($arg);
}
elseif (isset($this->conf['access block'])) {
$block = @$this->conf['access block'];
$path = '';
if (isset($this->conf['access path'])) {
$path = $this->conf['access path'];
}
return FrxReportGenerator::instance()
->block_access($block, $path, $arg);
}
else {
return user_access('access content');
}
}
protected function loadBlockFromDB($block_name) {
$block = array();
// IF load from the database if forena_query is there.
if (module_exists('forena_query')) {
// See if we have one in the database first
$sql = 'SELECT * FROM {forena_data_blocks} WHERE repository=:repos AND block_name = :block_name';
$rs = db_query($sql, array(
':repos' => $this->name,
':block_name' => $block_name,
));
if ($b = $rs
->fetchObject()) {
$block = array(
'repository' => $b->repository,
'block_name' => $b->block_name,
'type' => $b->block_type,
'file' => $b->src,
'builder' => $b->builder,
'access' => $b->access,
'title' => $b->title,
'locked' => $b->locked,
'modified' => $b->modified,
);
switch ($block['type']) {
case 'sql':
$block = array_merge($block, $this
->parseSQLFile($block['file']));
break;
case 'xml':
$block = array_merge($block, $this
->parseXMLFile($block['file']));
break;
}
if ($block['builder']) {
$block['builder'] = unserialize($block['builder']);
}
}
}
return $block;
}
protected function loadBlockFromFile($block_name) {
$base_file = $this->block_path . '/' . $block_name;
$parts = @explode('.', $block_name);
$php_method = array_pop($parts);
$php_class = implode('.', $parts);
$php_file = $this->block_path . '/' . $php_class . '.inc';
if (file_exists($base_file . '.sql')) {
$contents = file_get_contents($base_file . '.sql');
$block = $this
->parseSQLFile($contents);
$block['type'] = 'sql';
}
elseif (file_exists($base_file . '.xml')) {
$contents = file_get_contents($base_file . '.xml');
$block = $this
->parseXMLFile($contents);
$block['type'] = 'xml';
}
elseif (file_exists($php_file)) {
require_once $php_file;
if (class_exists($php_class)) {
$o = new $php_class();
$block['type'] = 'php';
$block['access'] = @$o->access;
$block['object'] = $o;
$block['method'] = $php_method;
if (method_exists($o, 'tokens')) {
$block['tokens'] = $o
->tokens();
}
elseif (isset($o->tokens)) {
$block['tokens'] = $o->tokens;
}
else {
$block['tokens'] = array();
}
}
}
else {
return array();
}
$block['locked'] = 1;
return $block;
}
/**
* Load blcok data from filesystem
* @param $block_name
*/
function loadBlock($block_name, $include = FALSE) {
$block = array();
if ($include) {
$this->block_name = $block_name;
}
$block = $this
->loadBlockFromDB($block_name);
if (!$block) {
$block = $this
->loadBlockFromFile($block_name);
}
return $block;
}
/**
* Load tokens from block source
*/
public function tokens($source) {
$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($source);
$tokens = array_diff($tokens, array(
'current_user',
));
//check tokens in the where clause
}
return $tokens;
}
public function listDBBlocks($search, &$data_blocks) {
$search = '%' . $search . '%';
$sql = 'SELECT * from {forena_data_blocks} WHERE repository=:repos
AND block_name like :search ';
$rs = db_query($sql, array(
':repos' => $this->name,
':search' => $search,
));
foreach ($rs as $block) {
$data_blocks[] = $block->block_name;
}
}
/**
* Find all the blocks matching a provided search string
*
* @param string $search part block names to search for
* @return unknown
*/
public function list_blocks($search, &$block_list, $subdir = '') {
static $count = 0;
// First find files that match the search string
if ($count > 100) {
return;
}
$path = $this->block_path . '/';
if ($subdir) {
$path .= $subdir . '/';
}
$block_path = $path . '*' . $search . '*';
// Find sql files
$d = glob($block_path);
if ($d) {
foreach ($d as $file_name) {
// Split off the extention
$p = strripos($file_name, '.');
if ($p !== FALSE) {
$ext = substr($file_name, $p + 1);
$block_name = substr($file_name, 0, $p);
}
else {
$ext = '';
$block_name = $file_name;
}
switch ($ext) {
case 'inc':
require_once $file_name;
$class = str_replace($this->block_path . '/', '', $block_name);
$methods = get_class_methods($class);
if ($methods) {
foreach ($methods as $method) {
if ($method != 'tokens') {
$block_list[] = $class . '.' . $method;
}
}
}
break;
default:
if (array_search($ext, $this->block_extensions) !== FALSE) {
$block_list[] = str_replace($this->block_path . '/', '', $block_name);
}
}
}
}
$count++;
// Find directories
$d = glob($path . '*');
if ($d) {
foreach ($d as $dir_name) {
if (is_dir($dir_name)) {
$dir_name = str_replace($this->block_path . '/', '', $dir_name);
$this
->list_blocks($search, $block_list, $dir_name);
}
}
}
// Date
if (!$subdir && module_exists('forena_query')) {
$this
->listDBBlocks($search, $block_list);
}
}
public function debug($msg = '', $log = '') {
FrxReportGenerator::instance()->app
->debug($msg, $log);
}
public function error($msg = '', $log = '') {
if ($msg) {
drupal_set_message(check_markup($msg), 'error');
}
if ($log) {
watchdog('forena', $log, NULL, WATCHDOG_ERROR);
}
}
public function parseXMLFile($contents) {
$comment = $this->comment_prefix;
$trim = '->';
$lines = explode("\n", $contents);
$cnt = count($lines);
$access = '';
$i = 0;
$block = '';
$data = '';
while ($i < $cnt) {
$l = trim($lines[$i], "\r");
@(list($d, $c) = explode($comment, $l, 2));
if ($trim) {
$c = trim($c, $trim);
}
if ($c) {
list($a, $o) = explode('=', $c, 2);
$a = trim($a);
if ($a && $o) {
switch ($a) {
case 'ACCESS':
$access = trim($o);
break;
default:
}
}
}
if (strpos($l, $comment) !== 0) {
$data .= "{$l}\n";
}
$i++;
}
return array(
'access' => $access,
'source' => $data,
'tokens' => $this
->tokens($data),
);
}
public function getSQLInclude($block_name) {
//@TODO: allow relative block includes
$block = $this
->loadBlock($block_name, TRUE);
if ($block['type'] == 'sql') {
return $block;
}
}
public function parseSQLFile($contents) {
$comment = $this->comment_prefix;
$trim = $this->comment_suffix;
$lines = explode("\n", $contents);
$cnt = count($lines);
$access = '';
$i = 0;
$block = '';
$parms = Frx::Data()
->currentContext();
$data = '';
$source = '';
$file = '';
$skip = FALSE;
$in_info = FALSE;
$info_text = '';
$tokens = array();
$options = array();
while ($i < $cnt) {
$l = trim($lines[$i], "\r");
@(list($d, $c) = explode($comment, $l, 2));
if ($trim) {
$c = trim($c, $trim);
}
if ($c) {
$c = trim($c);
@(list($a, $o) = explode('=', $c, 2));
$a = trim($a);
if ($a && $o || $c == 'END' || $c == 'ELSE' || $c == 'INFO') {
if ($c != 'INFO') {
$in_info = false;
}
switch ($a) {
case 'ACCESS':
$access = trim($o);
break;
case 'SWITCH':
$switch = trim($o);
$found_case = FALSE;
break;
case 'CASE':
dpm($this->te
->replace($switch), 'SWITCH');
$match = $this->te
->replace($switch, TRUE) == $this->te
->replace($o);
if ($match) {
$found_case = TRUE;
}
$skip = !$match;
break;
case 'IF':
$skip = !$this->te
->test(trim($o));
break;
case 'END':
$skip = FALSE;
$switch = '';
break;
case 'ELSE':
$skip = $switch ? $found_case : !$skip;
break;
case 'INFO':
$in_info = TRUE;
break;
case 'INCLUDE':
$inc_block = $this
->getSQLInclude(trim($o));
if ($inc_block) {
$data .= $inc_block['source'];
$tokens = array_merge($tokens, $inc_block['tokens']);
}
break;
}
}
if ($a != 'ACCESS') {
$file .= "{$l}\n";
}
}
else {
$file .= "{$l}\n";
}
if ($in_info) {
if (strpos($l, $comment) !== 0 && $l) {
$info_text .= "{$l}\n";
}
}
elseif (!$skip) {
if (strpos($l, $comment) !== 0 && $l) {
$data .= "{$l}\n";
}
}
$i++;
}
$tokens = array_merge($tokens, $this
->tokens($contents));
$options = drupal_parse_info_format($info_text);
$block = array(
'source' => $data,
'file' => trim($file, " \n"),
'tokens' => $tokens,
'options' => $options,
);
if ($access) {
$block['access'] = $access;
}
return $block;
}
/**
* Dummy method for returning sql data
* @param $parameters array Block parameters
* @param $block array extra block options for data provider.
*/
public function sqlData($parameters, $options = array()) {
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 = $source;
$xml = new SimpleXMLElement($xmlData);
} catch (Exception $e) {
$this
->error("Error processing xml\n", $e
->getMessage() . "\n" . $xmlData);
}
return $xml;
}
public function phpData($o, $method, $parameters) {
$data = NULL;
if (is_object($o) && is_callable(array(
$o,
$method,
))) {
$data = $o
->{$method}($parameters);
}
return $data;
}
/**
* Save a data block
* @param $block_name String name of block to save
* @param $data array fields of block to save.
*/
public function saveBlock($block_name, $data) {
$modified = time();
$builder = @$data['builder'];
if (is_array($builder)) {
$builder = serialize($builder);
}
$rs = db_query('SELECT * from {forena_data_blocks} WHERE repository=:repos AND
block_name = :block_name', array(
':repos' => $this->name,
':block_name' => $block_name,
));
if ($block = $rs
->fetchObject()) {
db_update('forena_data_blocks')
->fields(array(
'src' => $data['file'],
'builder' => $builder,
'access' => $data['access'],
'modified' => $modified,
))
->condition('repository', $this->name)
->condition('block_name', $block_name)
->execute();
}
else {
db_insert('forena_data_blocks')
->fields(array(
'repository' => $this->name,
'block_name' => $block_name,
'block_type' => $data['type'],
'src' => $data['file'],
'builder' => $builder,
'access' => $data['access'],
'locked' => 0,
'modified' => $modified,
))
->execute();
}
}
/**
*
* Delete data block stored in database.
* @param $block_name Data block to delete
*/
public function deleteBlock($block_name) {
db_delete('forena_data_blocks')
->condition('repository', $this->name)
->condition('block_name', $block_name)
->execute();
}
/**
* Build the SQL clause based on builder data.
* @param $data
*/
public function buildFilterSQL($data) {
$clause = '';
$op = $data['op'];
$i = 0;
if ($data['filter']) {
foreach ($data['filter'] as $cond) {
$i++;
$conj = $i == 1 ? '' : $op . ' ';
if (isset($cond['filter'])) {
$clause .= $conj . ' (' . $this
->buildFilterSQL($cond) . " )\n";
}
else {
switch ($cond['op']) {
case 'IS NULL':
case 'IS NOT NULL':
$expr = $cond['field'] . ' ' . $cond['op'];
break;
default:
$expr = $cond['field'] . ' ' . $cond['op'] . ' ' . $this
->format($cond['value'], $cond['field'], array());
}
$clause .= ' ' . $conj . $expr;
}
}
}
return $clause;
}
/**
* Perform generic type conversion based on attributes.
* @param $key The token key for parameter replacement.
* @param $value The value of the parameter
* @return Ambigous <NULL, array>
*/
public function parmConvert($key, $value) {
if (isset($this->types[$key]) && $this->types[$key]) {
if ($value === NULL || $value === '') {
$value = NULL;
}
else {
switch (strtolower($this->types[$key])) {
case 'date':
$time = @new DateTime($value);
if ($time) {
$value = date_format($time, 'Y-m-d H:i:s');
}
else {
$value = NULL;
}
break;
case 'unixtime':
$time = @new DateTime($value);
if ($time) {
$value = $time
->getTimeStamp();
}
else {
$value = NULL;
}
break;
case 'numeric':
case 'float':
$value = (double) $value;
break;
case 'int':
case 'integer':
$value = (int) $value;
break;
case 'array':
$value = (array) $value;
break;
}
}
}
return $value;
}
}
Classes
Name | Description |
---|---|
FrxDataSource | @file Class that defines default methods for access control in an FrxDataSource |