| Current Path : /home/bonneesp/www/plugins/editors-xtd/tabulizer/tabulizer/assets/ |
| Current File : /home/bonneesp/www/plugins/editors-xtd/tabulizer/tabulizer/assets/class.php |
<?php
/**
* @version 6.5.0 tabulizer $
* @package tabulizer
* @copyright Copyright © 2011 - All rights reserved.
* @license GNU/GPL
* @author Dimitrios Mourloukos
* @author mail info@alterora.gr
* @website www.tabulizer.com
*
*/
// no direct access
defined('_JEXEC') or die('Restricted access');
require_once(TABULIZER_INCLUDE_PATH . 'assets' .DIRECTORY_SEPARATOR. 'helper.php');
class Tabulizer {
var $rules_dir = '.';
var $use_comments = false;
var $strict_column_consistency = true;
function setDir($rules_dir) {
$this->rules_dir = $rules_dir;
}
function setComments($value) {
$this->use_comments = $value;
}
function setColumnConsistency($value) {
$this->strict_column_consistency = $value;
}
function parseInput($text, $separator, $enclosure, &$rows) {
if (empty($text) || empty($separator)) return;
$escape = '"';
$row_id = 1;
$lines = explode("\n", $text);
foreach ($lines as $line) {
$line = trim($line); if (empty($line)) continue;
$columns = TabulizerString::my_str_getcsv ( $line, $separator, $enclosure, $escape);
$column_id = 1;
foreach ($columns as $cell) {
$rows[$row_id][$column_id] = $cell;
$column_id++;
}
$row_id++;
}
}
function validateTableRows(&$rows, &$errors) {
if (empty($rows)) {
$errors[] = JText::_('COM_TABULIZER_NO_INPUT_TEXT');
return false;
}
$column_count = 0;
$column_count_row = 0;
$column_count_max = 0;
$fix_column_consistency = false;
foreach ($rows as $row_id => $row) {
$count = count($row);
if ($column_count == 0) {
$column_count = $count;
$column_count_row = $row_id;
} else if ($count != $column_count) {
if ($this->strict_column_consistency) {
$errors[] = sprintf(JText::_('COM_TABULIZER_COLUMNS_COUNT_DISCREPANCY'), $column_count_row, $column_count, $row_id, $count); // ERROR_CODE_NUM_OF_COLUMN_DISCREPANCY;
return false;
} else {
$fix_column_consistency = true;
}
}
if ($count > $column_count_max) $column_count_max = $count;
}
if ($fix_column_consistency) {
foreach ($rows as $row_id => &$row) {
$count = count($row);
while ($count < $column_count_max) {
$row[] = '';
$count++;
}
}
}
return true;
}
function parseRowColumnRange($value, $row_id=null, $column_id=null) {
$value = str_replace(' ','',$value);
if (empty($value)) return null;
$range = null;
$row_from = $row_to = $column_from = $column_to = 0;
list($row_range, $column_range) = explode(',', $range);
if (!empty($row_range)) {
list($row_from,$row_to) = explode(':',$row_range);
if (!empty($row_from)) {
if ($row_from = 'SAME') $row_from = $row_id;
else if ($row_from = 'ALL') $row_from = 0;
else $row_from = intval($row_from);
}
if (!empty($row_from)) $range['row_from'] = $row_from;
if (!empty($row_to)) {
if ($row_to = 'SAME') $row_to = $row_id;
else if ($row_to = 'ALL') $row_to = 0;
else $row_to = intval($row_to);
}
if (!empty($row_to)) $range['row_to'] = $row_to;
}
if (!empty($column_range)) {
list($column_from,$column_to) = explode(':',$column_range);
if (!empty($column_from)) {
if ($column_from = 'SAME') $column_from = $column_id;
else if ($column_from = 'ALL') $column_from = 0;
else $column_from = intval($column_from);
}
if (!empty($column_from)) $range['column_from'] = $column_from;
if (!empty($column_to)) {
if ($column_to = 'SAME') $column_to = $column_id;
else if ($column_to = 'ALL') $column_to = 0;
else $column_to = intval($column_to);
}
if (!empty($column_to)) $range['column_to'] = $column_to;
}
// adjust range limits
if (empty($row_from)) {
if (!empty($row_to)) $row_from = 1;
}
if (empty($row_to)) {
if (!empty($row_from)) $row_to = $row_from;
}
if (empty($column_from)) {
if (!empty($column_to)) $column_from = 1;
}
if (empty($column_to)) {
if (!empty($column_from)) $column_to = $column_from;
}
$range = array('str'=> $value, 'row_from'=>$row_from, 'row_to'=>$row_to, 'column_from'=>$column_from, 'column_to'=>$column_to);
return $range;
}
function is_my_numeric($str) {
return TabulizerMath::getNumericValue($str);
}
function getValuesCalculation($values, $op) {
$value = '';
if (empty($values)) return $value;
switch ($op) {
case 'add':
$sum = 0;
foreach ($values as $value) {
$sum += $value;
}
$value = $sum;
break;
case 'mul':
$sum = 1;
foreach ($values as $value) {
$sum *= $value;
}
$value = $sum;
break;
case 'avg':
$sum = 0;
foreach ($values as $value) {
$sum += $value;
}
$value = ($sum / count($values));
break;
case 'med':
sort($values, SORT_NUMERIC);
$median_index = round(count($values) /2, 0, PHP_ROUND_HALF_DOWN);
$value = $values[$median_index];
break;
case 'min':
$value = min($values);
break;
case 'max':
$value = max($values);
break;
}
return $value;
}
function getCellCalculation($calculation, $row_id, $column_id, &$rows) {
// sanity check
if (empty($rows)) return null;
// backward compatibility
if (is_numeric($calculation)) {
switch ($calculation) {
case CALCULATION_ADD_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'add'; break;
case CALCULATION_ADD_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'add'; break;
case CALCULATION_ADD_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'add'; break;
case CALCULATION_ADD_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'add'; break;
case CALCULATION_MUL_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'mul'; break;
case CALCULATION_MUL_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'mul'; break;
case CALCULATION_MUL_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'mul'; break;
case CALCULATION_MUL_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'mul'; break;
case CALCULATION_AVG_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'avg'; break;
case CALCULATION_AVG_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'avg'; break;
case CALCULATION_AVG_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'avg'; break;
case CALCULATION_AVG_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'avg'; break;
case CALCULATION_MED_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'med'; break;
case CALCULATION_MED_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'med'; break;
case CALCULATION_MED_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'med'; break;
case CALCULATION_MED_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'med'; break;
case CALCULATION_MIN_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'min'; break;
case CALCULATION_MIN_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'min'; break;
case CALCULATION_MIN_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'min'; break;
case CALCULATION_MIN_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'min'; break;
case CALCULATION_MAX_ABOVE: $i_from = 1; $i_to = $row_id-1; $j_from = $column_id; $j_to = $column_id; $op = 'max'; break;
case CALCULATION_MAX_BELOW: $i_from = $row_id+1; $i_to = count($rows); $j_from = $column_id; $j_to = $column_id; $op = 'max'; break;
case CALCULATION_MAX_LEFT: $i_from = $row_id; $i_to = $row_id; $j_from = 1; $j_to = $column_id-1; $op = 'max'; break;
case CALCULATION_MAX_RIGHT: $i_from = $row_id; $i_to = $row_id; $j_from = $column_id+1; $j_to = count($rows[0]); $op = 'max'; break;
default: return null;
}
$values = array();
for ($i=$i_from;$i<=$i_to;$i++) {
for ($j=$j_from;$j<=$j_to;$j++) {
$value = $rows[$i][$j];
$numeric_value = $this->is_my_numeric(trim($value));
if (is_numeric($numeric_value)) {
$values[] = $numeric_value;
}
}
}
if (empty($values)) return null;
else return $this->getValuesCalculation($values, $op);
} else {
$calculation_value = null;
$function_name = null;
$args_element = null;
$args_range = null;
$custom_arg = null;
$parts = explode(CALCULATION_SEP,$calculation);
if (count($parts)==4) {
$function_name = $parts[0];
$element = $parts[1];
$element_range = $parts[2];
$custom_arg = $parts[3];
$element_range_ids = null;
$values = array();
switch ($element) {
case 'row':
$last = count($rows[1]);
$element_range_ids = $this->getRangeIds($element_range, 0, $last, null, null);
if ($element_range_ids) {
foreach ($element_range_ids as $id) {
$value = $rows[$row_id][$id];
$values["{$row_id},{$id}"] = $value;
}
}
break;
case 'column':
$last = count($rows);
$element_range_ids = $this->getRangeIds($element_range, 0, $last, null, null);
if ($element_range_ids) {
foreach ($element_range_ids as $id) {
$value = $rows[$id][$column_id];
$values["{$id},{$column_id}"] = $value;
}
}
break;
case 'cell':
$element_range_ids = $this->getCellRangeIds($element_range, $rows);
if ($element_range_ids) {
foreach ($element_range_ids as $id) {
list($rid, $cid) = explode(',',$id);
$value = $rows[$rid][$cid];
$values["{$rid},{$cid}"] = $value;
}
}
break;
}
if (!empty($function_name) && !empty($values)) {
$function_name = strtolower($function_name);
// sanity check
if (preg_match('/^([a-z\d_]+)$/',$function_name,$matches)) {
$function_file = JPATH_SITE .DIRECTORY_SEPARATOR. RULES_CALC_DIR . $function_name . '.php';
if (file_exists($function_file)) {
require_once($function_file);
$class_name = 'TabulizerCalc'.ucfirst($function_name);
if (class_exists($class_name)) {
$class = new $class_name();
if (method_exists($class, 'calc')) {
$calculation_value = $class->calc($row_id, $column_id, $values, $custom_arg);
}
}
}
}
}
}
return $calculation_value;
}
}
function my_ucfirst($string) {
$string = mb_strtoupper(mb_substr($string, 0, 1)) . mb_substr($string, 1);
return $string;
}
function my_ucwords($string) {
$words = explode(' ',$string);
foreach ($words as &$word) {
$word = my_ucfirst($word);
}
$string = implode(' ',$words);
return $string;
}
function createAutospanTable($rows, &$autospan_table) {
if (empty($rows)) return;
$num_of_rows = count($rows);
$num_of_columns = count($rows[1]);
$area = 'columns';
for ($row_id = 1; $row_id <= $num_of_rows; $row_id++) {
$counter = 1;
for ($column_id = 1; $column_id <= $num_of_columns; $column_id++) {
$cell = trim($rows[$row_id][$column_id]);
if (!empty($cell)) {
$counter++;
} else if (!$counter) {
$counter = 1;
}
$autospan_table[$area][$row_id][$column_id] = $counter;
}
}
$area = 'rows';
for ($column_id = 1; $column_id <= $num_of_columns; $column_id++) {
$counter = 0;
for ($row_id = 1; $row_id <= $num_of_rows; $row_id++) {
$cell = trim($rows[$row_id][$column_id]);
if (!empty($cell)) {
$counter++;
} else if (!$counter) {
$counter = 1;
}
$autospan_table[$area][$row_id][$column_id] = $counter;
}
}
}
function parseRangeStr($range_str, $range_key, $last, $area, $autospan_table) {
$ids = array();
$parts = explode(',',$range_str);
foreach ($parts as $range) {
// replace L\d with actual number
while (preg_match( '/(\W|^)L([\d]+)(\W|$)/', $range, $matches)) {
$l_id = $last - intval($matches[2]) + 1;
$replace_from = $matches[0];
$replace_to = $matches[1] . $l_id . $matches[3];
$range = str_replace($replace_from,$replace_to,$range);
}
if (is_numeric($range)) {
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if ($range_id == $range) $ids[] = $id;
}
} else {
$range = intval($range);
if ($range <= $last) {
$ids[] = $range;
}
}
} else if (preg_match( '/^([\d]+)-([\d]+)$/', $range, $matches)) {
$from = intval($matches[1]);
$to = intval($matches[2]);
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
$to = ($last<$to)?$last:$to;
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^>([\d]+)$/', $range, $matches)) {
$from = intval($matches[1])+1;
$to = $last;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^<([\d]+)$/', $range, $matches)) {
$from = 1;
$to = intval($matches[1])-1;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
$to = ($last<$to)?$last:$to;
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^>=([\d]+)$/', $range, $matches)) {
$from = intval($matches[1]);
$to = $last;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^<=([\d]+)$/', $range, $matches)) {
$from = 1;
$to = intval($matches[1]);
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
$to = ($last<$to)?$last:$to;
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^FIRST([\d]+)$/', $range, $matches)) {
$from = 1;
$to = intval($matches[1]);
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
$to = ($last<$to)?$last:$to;
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^LAST([\d]+)$/', $range, $matches)) {
$from = $last - intval($matches[1])+1;
$to = $last;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id >= $from)&&($range_id<=$to)) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
$ids[] = $id;
}
}
} else if (preg_match( '/^MOD([\d]+)$/', $range, $matches)) {
$from = 1;
$to = $last;
$mod = intval($matches[1]);
if ($mod) {
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if ($range_id % $mod == 0) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
if ($id % $mod == 0) $ids[] = $id;
}
}
}
} else if (preg_match( '/^MOD([\d]+)\[(.+)\]$/', $range, $matches)) { // backward compatibility
$from = 1;
$to = $last;
$mod = intval($matches[1]);
$subrange = $matches[2];
if (preg_match( '/^([\d]+)-([\d]+)$/', $subrange, $submatches)) {
$from = intval($submatches[1]);
$to = intval($submatches[2]);
} else if (preg_match( '/^>([\d]+)$/', $subrange, $submatches)) {
$from = intval($submatches[1])+1;
} else if (preg_match( '/^<([\d]+)$/', $subrange, $submatches)) {
$to = intval($submatches[1])-1;
} else if (preg_match( '/^>=([\d]+)$/', $subrange, $submatches)) {
$from = intval($submatches[1]);
} else if (preg_match( '/^<=([\d]+)$/', $subrange, $submatches)) {
$to = intval($submatches[1]);
} else if (preg_match( '/^FIRST([\d]+)$/', $subrange, $submatches)) {
$to = intval($submatches[1]);
} else if (preg_match( '/^LAST([\d]+)$/', $subrange, $submatches)) {
$from = $last - intval($submatches[1])+1;
}
if ($mod) {
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (($range_id - $from) % $mod == 0) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
if (($id - $from) % $mod == 0) $ids[] = $id;
}
}
}
} else if ($range == 'ODD') {
$from = 1;
$to = $last;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if ($range_id % 2) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
if ($id % 2 ) $ids[] = $id;
}
}
} else if ($range == 'EVEN') {
$from = 1;
$to = $last;
if ($range_key) {
for ($id=1;$id<=$last;$id++) {
$range_id = $this->getRangeKeyId($id, $range_key, $area, $autospan_table);
if (!($range_id % 2)) $ids[] = $id;
}
} else {
for ($id=$from; $id<=$to;$id++) {
if (!($id % 2)) $ids[] = $id;
}
}
}
}
return $ids;
}
function getRangeIds($range, $range_key, $last, $area, $autospan_table) {
$range_ids = array();
$range = strtoupper(str_replace(' ','', trim($range)));
# <> are not allowed in the XML files, so replace them with LT and GT
$gl_values = array('LTE','LT','GTE','GT');
$sy_values = array('<=','<','>=','>');
$range = str_replace($gl_values, $sy_values, $range);
if (!empty($range)) {
$subranges = explode(';',$range);
foreach ($subranges as $subrange) {
$subrange_info = array('include'=>array(), 'exclude'=>array(), 'filter'=>array());
$subrange_str = '';
$subrange_flag = 'include';
if (empty($subrange)) continue;
$sbn = strlen($subrange);
for ($sbi = 0; $sbi < $sbn; $sbi++) {
$sbc = $subrange{$sbi};
if ($sbc==RANGE_FILTER_SEP) {
if (!empty($subrange_str)) $subrange_info[$subrange_flag][] = $this->parseRangeStr($subrange_str, $range_key, $last, $area, $autospan_table);
$subrange_str = '';
$subrange_flag = 'filter';
} else if ($sbc==RANGE_EXCLUDE_SEP) {
if (!empty($subrange_str)) $subrange_info[$subrange_flag][] = $this->parseRangeStr($subrange_str, $range_key, $last, $area, $autospan_table);
$subrange_str = '';
$subrange_flag = 'exclude';
} else {
$subrange_str .= $sbc;
}
}
$subrange_info[$subrange_flag][] = $this->parseRangeStr($subrange_str, $range_key, $last, $area, $autospan_table);
$subrange_str = '';
// combine all ids together, for the current subrange
$ids = null;
if (!empty($subrange_info['include'])) {
foreach ($subrange_info['include'] as $include_ids) {
if (empty($ids)) $ids = $include_ids; else $ids = array_unique(array_merge($ids, $include_ids));
}
}
if (!empty($ids)) {
if (!empty($subrange_info['filter'])) {
foreach ($subrange_info['filter'] as $filter_ids) {
$ids = array_intersect ($ids, $filter_ids);
}
}
}
if (!empty($ids)) {
if (!empty($subrange_info['exclude'])) {
foreach ($subrange_info['exclude'] as $exclude_ids) {
$ids = array_diff ($ids, $exclude_ids);
}
}
}
if (!empty($ids)) {
if (empty($range_ids)) $range_ids = array_unique($ids);
else $range_ids = array_unique(array_merge($range_ids, $ids));
}
}
}
return $range_ids;
}
function getRangeKeyId($id, $range_key, $area, &$autospan_table) {
if ($area == 'rows') {
return $autospan_table['rows'][$id][$range_key];
} else if ($area == 'columns') {
return $autospan_table['columns'][$range_key][$id];
} else {
return $id;
}
}
function searchCellRangeNumeric($numeric_value, $cell_range, $row_id, $column_id, $rows) {
$in_range = true;
$range_found = false;
if (isset($cell_range['from_value'])) {
if ($numeric_value < $cell_range['from_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['to_value'])) {
if ($numeric_value > $cell_range['to_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['gt_value'])) {
if ($numeric_value <= $cell_range['gt_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['lt_value'])) {
if ($numeric_value >= $cell_range['lt_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['eq_value'])) {
if ($numeric_value != $cell_range['equal_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['min_range'])) {
$search_range = $this->parseRowColumnRange($cell_range['min_range'],$row_id,$column_id);
if (isset($search_range)) {
if (!isset($search_values['min'][$search_range['str']])) {
$this->searchTableNumericValue('min',$search_range['str'],$search_range['row_from'],$search_range['row_to'],$search_range['column_from'],$search_range['column_to'],$rows,$search_values);
}
$search_value = $search_values['min'][$search_range['str']];
if (is_numeric($search_value)) {
if ($numeric_value != $search_value) $in_range = false;
}
}
$range_found = true;
}
if (isset($cell_range['max_range'])) {
$search_range = $this->parseRowColumnRange($cell_range['max_range'],$row_id,$column_id);
if (isset($search_range)) {
if (!isset($search_values['max'][$search_range['str']])) {
$this->searchTableNumericValue('max',$search_range['str'],$search_range['row_from'],$search_range['row_to'],$search_range['column_from'],$search_range['column_to'],$rows,$search_values);
}
$search_value = $search_values['max'][$search_range['str']];
if (is_numeric($search_value)) {
if ($numeric_value != $search_value) $in_range = false;
}
}
$range_found = true;
}
if (isset($cell_range['median_range'])) {
$search_range = $this->parseRowColumnRange($cell_range['median_range'],$row_id,$column_id);
if (isset($search_range)) {
if (!isset($search_values['med'][$search_range['str']])) {
$this->searchTableNumericValue('med',$search_range['str'],$search_range['row_from'],$search_range['row_to'],$search_range['column_from'],$search_range['column_to'],$rows,$search_values);
}
$search_value = $search_values['med'][$search_range['str']];
if (is_numeric($search_value)) {
if ($numeric_value != $search_value) $in_range = false;
}
}
$range_found = true;
}
if ($in_range && $range_found) {
return true;
} else {
return false;
}
}
function searchCellRangeText($str_value, $cell_range) {
$in_range = true;
$range_found = false;
$str_value_raw = $str_value;
$str_value = strip_tags($str_value);
$str_value_upper = mb_strtoupper($str_value);
if (isset($cell_range['same_value'])) {
if ($str_value != $cell_range['same_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['samei_value'])) {
if ($str_value_upper != $cell_range['samei_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['samen_value'])) {
if ($str_value == $cell_range['samen_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['sameni_value'])) {
if ($str_value_upper == $cell_range['sameni_value']) $in_range = false;
$range_found = true;
}
if (isset($cell_range['contain_value'])) {
if (mb_ereg($cell_range['contain_value'], $str_value)===false) $in_range = false;
$range_found = true;
}
if (isset($cell_range['containi_value'])) {
if (mb_eregi($cell_range['containi_value'], $str_value)===false) $in_range = false;
$range_found = true;
}
if (isset($cell_range['containn_value'])) {
if (mb_ereg($cell_range['containn_value'], $str_value)!==false) $in_range = false;
$range_found = true;
}
if (isset($cell_range['containni_value'])) {
if (mb_eregi($cell_range['containni_value'], $str_value)!==false) $in_range = false;
$range_found = true;
}
if (isset($cell_range['containt_value'])) {
if (mb_eregi($cell_range['containt_value'], $str_value_raw)!==false) $in_range = false;
$range_found = true;
}
if ($in_range && $range_found) {
return true;
} else {
return false;
}
}
function searchTableNumericValue($operation, $range_key, $row_from, $row_to, $column_from, $column_to, $rows, &$search_values) {
$value = null;
$values = array();
foreach ($rows as $row_id => $row) {
foreach ($row as $column_id=> $cell) {
if (!empty($row_from) && ($row_id<$row_from)) continue;
if (!empty($row_to) && ($row_id>$row_to)) continue;
if (!empty($column_from) && ($column_id<$column_from)) continue;
if (!empty($column_to) && ($column_id>$column_to)) continue;
$numeric_value = $this->is_my_numeric(trim($cell));
if (is_numeric($numeric_value)) {
$values[] = $numeric_value;
}
}
}
if (!empty($values)) {
switch ($operation) {
case 'min':
$value = min($values);
break;
case 'max':
$value = max($values);
break;
case 'med':
sort($values, SORT_NUMERIC);
$median_index = round(count($values) /2, 0, PHP_ROUND_HALF_DOWN);
$value = $values[$median_index];
break;
}
}
if (!isset($search_values[$operation])) $search_values[$operation] = array();
$search_values[$operation][$range_key] = $value;
}
function parseCellRangeStr($range, &$cell_ids, &$cell_ranges) {
$range_raw = $range;
$range = strtoupper(str_replace(' ','', trim($range)));
# <> are not allowed in the XML files, so replace them with LT and GT
$gl_values = array('LTE','LT','GTE','GT');
$sy_values = array('<=','<','>=','>',);
$range = str_replace($gl_values, $sy_values, $range);
if (preg_match( '/^([\d]+),([\d]+)$/', $range, $matches)) {
$from = intval($matches[1]);
$to = intval($matches[2]);
$cell_ids[] = array('row_id'=>$from, 'column_id' =>$to);
} else if (preg_match( '/^([-+]?[0-9]*\.?[0-9]+)-([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$from = floatval($matches[1]);
$to = floatval($matches[2]);
$cell_ranges[] = array('from_value'=>$from, 'to_value' =>$to);
} else if (preg_match( '/^>=([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$from = floatval($matches[1]);
$cell_ranges[] = array('from_value'=>$from);
} else if (preg_match( '/^<=([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$to = floatval($matches[1]);
$cell_ranges[] = array('to_value' =>$to);
} else if (preg_match( '/^=([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$value = floatval($matches[1]);
$cell_ranges[] = array('eq_value'=>$value);
} else if (preg_match( '/^>([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$from = floatval($matches[1]);
$cell_ranges[] = array('gt_value'=>$from);
} else if (preg_match( '/^<([-+]?[0-9]*\.?[0-9]+)$/', $range, $matches)) {
$to = floatval($matches[1]);
$cell_ranges[] = array('lt_value' =>$to);
} else if (preg_match( '/^SAMEI(.+)$/i', $range_raw, $matches)) {
$value = mb_strtoupper(trim($matches[1]));
$cell_ranges[] = array('samei_value'=>$value);
} else if (preg_match( '/^SAMENI(.+)$/i', $range_raw, $matches)) {
$value = mb_strtoupper(trim($matches[1]));
$cell_ranges[] = array('sameni_value'=>$value);
} else if (preg_match( '/^SAMEN(.+)$/i', $range_raw, $matches)) {
$value = mb_strtoupper(trim($matches[1]));
$cell_ranges[] = array('samen_value'=>$value);
} else if (preg_match( '/^SAME(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('same_value'=>$value);
} else if (preg_match( '/^CONTAINI(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('containi_value'=>$value);
} else if (preg_match( '/^CONTAINNI(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('containni_value'=>$value);
} else if (preg_match( '/^CONTAINN(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('containn_value'=>$value);
} else if (preg_match( '/^CONTAINT(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('containt_value'=>$value);
} else if (preg_match( '/^CONTAIN(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
$cell_ranges[] = array('contain_value'=>$value);
} else if (preg_match( '/^MIN(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
if ($value) $cell_ranges[] = array('min_range'=>$value);
} else if (preg_match( '/^MAX(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
if ($value) $cell_ranges[] = array('max_range'=>$value);
} else if (preg_match( '/^MEDIAN(.+)$/i', $range_raw, $matches)) {
$value = trim($matches[1]);
if ($value) $cell_ranges[] = array('median_range'=>$value);
}
}
function getCellRangeIds($range, &$rows) {
$range_ids = array();
$cell_ranges = array();
$cell_ids = array();
$range = trim($range);
if (!empty($range)) {
$subranges = explode(';',$range);
foreach ($subranges as $subrange) {
$this->parseCellRangeStr($subrange, $cell_ids, $cell_ranges);
}
}
if (!empty($cell_ids)) {
foreach ($cell_ids as $cell_id) {
$range_ids[] = $cell_id['row_id'] . ','. $cell_id['column_id'];
}
}
if (!empty($cell_ranges)) {
foreach ($rows as $row_id => $row) {
foreach ($row as $column_id => $cell) {
// numeric comparisons
$numeric_value = $this->is_my_numeric(trim($cell));
if (is_numeric($numeric_value)) {
foreach ($cell_ranges as $cell_range) {
$in_range = $this->searchCellRangeNumeric($numeric_value, $cell_range, $row_id, $column_id, $rows);
if ($in_range) {
$range_ids[] = $row_id . ','. $column_id;
}
}
}
// text comparisons
$str_value = trim($cell);
foreach ($cell_ranges as $cell_range) {
$in_range = $this->searchCellRangeText($str_value, $cell_range);
if ($in_range) {
$range_ids[] = $row_id . ','. $column_id;
}
}
}
}
} // cell ranges
return array_unique($range_ids);
}
function getCellFormatted($format, $value) {
if (empty($value)) return '';
list($data_type,$data_type_params) = explode(DATA_TYPE_SEPARATOR,$format);
$data_type_params = htmlspecialchars_decode($data_type_params,ENT_QUOTES);
switch ($data_type) {
case DATA_TYPE_TEXT:
$text_format = $data_type_params;
switch ($text_format) {
case FORMAT_TEXT_UPPERCASE: $value = mb_strtoupper($value); break;
case FORMAT_TEXT_LOWERCASE: $value = mb_strtolower($value); break;
case FORMAT_TEXT_UCFIRST: $value = my_ucfirst($value); break;
case FORMAT_TEXT_UCWORDS: $value = my_ucwords($value); break;
}
break;
case DATA_TYPE_NUMERIC:
$numeric_value = $this->is_my_numeric(trim($value));
if (is_numeric($numeric_value)) {
list($numeric_decimals, $numeric_dec_point, $numeric_thousands_sep) = explode(FORMAT_NUMERIC_SEPARATOR, $data_type_params);
$value = number_format ( $numeric_value , $numeric_decimals , getNumericPoint($numeric_dec_point) , getNumericPoint($numeric_thousands_sep) );
}
break;
case DATA_TYPE_CURRENCY:
list($currency_decimals, $currency_dec_point, $currency_thousands_sep, $currency_symbol, $currency_symbol_order) = explode(FORMAT_CURRENCY_SEPARATOR, $data_type_params);
if (!empty($currency_symbol)) {
$numeric_value = $this->is_my_numeric(trim(str_replace($currency_symbol, '', trim($value))));
} else {
$numeric_value = $this->is_my_numeric(trim($value));
}
if (is_numeric($numeric_value)) {
$value = number_format ( $numeric_value , $currency_decimals , getNumericPoint($currency_dec_point), getNumericPoint($currency_thousands_sep) );
switch ($currency_symbol_order) {
case FORMAT_CURRENCY_SYMBOL_ORDER_NONE: break;
case FORMAT_CURRENCY_SYMBOL_ORDER_BEFORE: $value = $currency_symbol . $value; break;
case FORMAT_CURRENCY_SYMBOL_ORDER_AFTER: $value = $value . $currency_symbol; break;
}
}
break;
case DATA_TYPE_DATE:
$timestamp_value = strtotime(trim($value));
if ($timestamp_value && ($timestamp_value>0)) {
$date_format = $data_type_params;
switch ($date_format) {
case FORMAT_DATE_DDMMYY_1: $date_format = "d-m-y"; $value = date($date_format, $timestamp_value); break; // 21-10-09
case FORMAT_DATE_DDMMYY_2: $date_format = "d/m/y"; $value = date($date_format, $timestamp_value); break; // 21/10/09
case FORMAT_DATE_MMDDYY_1: $date_format = "m-d-y"; $value = date($date_format, $timestamp_value); break; // 10-21-09
case FORMAT_DATE_MMDDYY_2: $date_format = "m/d/y"; $value = date($date_format, $timestamp_value); break; // 10/21/09
case FORMAT_DATE_DDMMYYYY_1: $date_format = "d-m-Y"; $value = date($date_format, $timestamp_value); break; // 21-10-2009
case FORMAT_DATE_DDMMYYYY_2: $date_format = "d/m/Y"; $value = date($date_format, $timestamp_value); break; // 21/10/2009
case FORMAT_DATE_DDMMYYYY_3: $date_format = "d/M/Y"; $value = date($date_format, $timestamp_value); break; // 21/Oct/2009
case FORMAT_DATE_MMDDYYYY_1: $date_format = "m-d-Y"; $value = date($date_format, $timestamp_value); break; // 10-21-2009
case FORMAT_DATE_MMDDYYYY_2: $date_format = "m/d/Y"; $value = date($date_format, $timestamp_value); break; // 10/21/2009
case FORMAT_DATE_MMDDYYYY_3: $date_format = "M j, Y"; $value = date($date_format, $timestamp_value); break; // Jan 1, 2009
case FORMAT_DATE_dDDMMYYYY_1: $date_format = "l, d-M-Y"; $value = date($date_format, $timestamp_value); break; // Monday, 21-Oct-2009
case FORMAT_DATE_dDDMMYYYY_2: $date_format = "l, d/M/Y"; $value = date($date_format, $timestamp_value); break; // Monday, 21/Oct/2009
case FORMAT_DATE_dMMDDYYYY_1: $date_format = "l, M j,Y"; $value = date($date_format, $timestamp_value); break; // Monday, Oct 1, 2009
case FORMAT_DATE_dMMDDYYYY_2: $date_format = "l, d-M-Y"; $value = date($date_format, $timestamp_value); break; // Monday, 21-Oct-2009
case FORMAT_DATE_dDDm_1: $date_format = "l, j M"; $value = date($date_format, $timestamp_value); break; // Monday, 21 October
case FORMAT_DATE_dmDD_1: $date_format = "l, M j"; $value = date($date_format, $timestamp_value); break; // Monday, October 21
}
}
break;
}
return $value;
}
function getCellReplaced($replacement, $value) {
if (empty($value)) return '';
list($case_sensitive,$replace_from,$replace_to) = explode(REPLACEMENT_SEPARATOR,$replacement,3);
$replace_from = htmlspecialchars_decode($replace_from,ENT_QUOTES);
$replace_to = htmlspecialchars_decode($replace_to,ENT_QUOTES);
if (!empty($replace_from)) {
if ($case_sensitive) {
$value = mb_ereg_replace ( $replace_from,$replace_to,$value);
} else {
$value = mb_eregi_replace ( $replace_from,$replace_to,$value);
}
}
return $value;
}
function getFormattedTable($rows, $ruleset) {
if (!empty($table_class_suffix)) $table_class_suffix = '-' . $table_class_suffix; else $table_class_suffix = '';
$num_of_rows = count($rows);
$num_of_columns = count($rows[1]);
// Calculation pre-process
foreach ($rows as $row_id => $row) {
foreach ($row as $column_id => $column) {
// calculation
$calculation = null;
if (isset($ruleset['rows'][$row_id]['calculation'])) $calculation = $ruleset['rows'][$row_id]['calculation'];
if (isset($ruleset['columns'][$column_id]['calculation'])) $calculation = $ruleset['columns'][$column_id]['calculation'];
if (isset($ruleset['cells'][$row_id][$column_id]['calculation'])) $calculation = $ruleset['cells'][$row_id][$column_id]['calculation'];
if (!empty($calculation)) {
$calculation_value = $this->getCellCalculation($calculation, $row_id, $column_id, $rows);
if (!is_null($calculation_value)) $rows[$row_id][$column_id] = $calculation_value;
}
}
}
// Autospan pre-process (colspan)
for ($row_id = 1; $row_id <= $num_of_rows; $row_id++) {
if (isset($ruleset['rows'][$row_id]['autospan'])) {
$row_start = null;
$column_start = null;
$colspan = 1;
for ($column_id = 1; $column_id <= $num_of_columns; $column_id++) {
$cell = trim($rows[$row_id][$column_id]);
if (empty($cell)) {
$ruleset['cells'][$row_id][$column_id]['autospan'] = 'IGNORE';
$colspan++;
} else {
if (isset($row_start)) {
if ($colspan > 1) {
$ruleset['cells'][$row_start][$column_start]['autospan'] = 'colspan="'.$colspan.'"';
$colspan = 1;
} else {
$ruleset['cells'][$row_start][$column_start]['autospan'] = '';
}
}
$row_start = $row_id;
$column_start = $column_id;
}
}
if (isset($row_start)) {
if ($colspan > 1) {
$ruleset['cells'][$row_start][$column_start]['autospan'] = 'colspan="'.$colspan.'"';
} else {
$ruleset['cells'][$row_start][$column_start]['autospan'] = '';
}
}
}
}
// Autospan pre-process (rowspan)
for ($column_id = 1; $column_id <= $num_of_columns; $column_id++) {
if (isset($ruleset['columns'][$column_id]['autospan'])) {
$row_start = null;
$column_start = null;
$rowspan = 1;
for ($row_id = 1; $row_id <= $num_of_rows; $row_id++) {
$cell = trim($rows[$row_id][$column_id]);
// ignore cells that have been colspaned
if (!empty($ruleset['cells'][$row_id][$column_id]['autospan'])) continue;
if (empty($cell)) {
$ruleset['cells'][$row_id][$column_id]['autospan'] = 'IGNORE';
$rowspan++;
} else {
if (isset($row_start)) {
if ($rowspan > 1) {
$ruleset['cells'][$row_start][$column_start]['autospan'] = 'rowspan="'.$rowspan.'"';
$rowspan = 1;
}
}
$row_start = $row_id;
$column_start = $column_id;
}
}
if (isset($row_start)) {
if ($rowspan > 1) {
$ruleset['cells'][$row_start][$column_start]['autospan'] = 'rowspan="'.$rowspan.'"';
} else {
$ruleset['cells'][$row_start][$column_start]['autospan'] = '';
}
}
}
}
if ($ruleset['style']) {
$ruleset_style_prefix = sprintf(TABULIZER_INCLUDE_STYLE_PREFIX,$ruleset['style']) . "\n";
if ($this->use_comments) {
$ruleset_style_prefix = '<!--'.$ruleset_style_prefix.'-->';
}
} else {
$ruleset_style_prefix = '';
}
$html = $ruleset_style_prefix . '<table class="tabtable'.$ruleset['suffix'].'">';
foreach ($rows as $row_id => $row) {
if (isset($ruleset['rows'][$row_id]['style'])) $row_class_append = $ruleset['rows'][$row_id]['style']; else $row_class_append = '';
$html .= '<tr class="tabrow '.$row_class_append.'">';
foreach ($row as $column_id => $column) {
// autospan
if (isset($ruleset['cells'][$row_id][$column_id]['autospan'])) {
$autospan = $ruleset['cells'][$row_id][$column_id]['autospan'];
if ($autospan =='IGNORE') {
// ignore cell
continue;
} else {
$column_autospan = $autospan;
}
} else $column_autospan = '';
// css style
$column_class_append = '';
if (isset($ruleset['columns'][$column_id]['style'])) $column_class_append .= ' ' . $ruleset['columns'][$column_id]['style'];
if (isset($ruleset['cells'][$row_id][$column_id]['style'])) $column_class_append .= ' ' . $ruleset['cells'][$row_id][$column_id]['style'];
// Replacement
$replacements = null;
if (isset($ruleset['rows'][$row_id]['replacement'])) $replacements = $ruleset['rows'][$row_id]['replacement'];
if (isset($ruleset['columns'][$column_id]['replacement'])) $replacements = $ruleset['columns'][$column_id]['replacement'];
if (isset($ruleset['cells'][$row_id][$column_id]['replacement'])) $replacements = $ruleset['cells'][$row_id][$column_id]['replacement'];
if (!empty($replacements)) {
foreach ($replacements as $replacement) {
$column = $this->getCellReplaced($replacement, $column);
}
}
// format
$format = null;
if (isset($ruleset['rows'][$row_id]['format'])) $format = $ruleset['rows'][$row_id]['format'];
if (isset($ruleset['columns'][$column_id]['format'])) $format = $ruleset['columns'][$column_id]['format'];
if (isset($ruleset['cells'][$row_id][$column_id]['format'])) $format = $ruleset['cells'][$row_id][$column_id]['format'];
if (!empty($format)) {
$column = $this->getCellFormatted($format, $column);
}
// put it all together
$html .= '<td '.$column_autospan.' class="tabcol '.$column_class_append.'">'. $column . '</td>';
}
$html .= "</tr>\n";
}
$html .= "</table>";
return $html;
}
function process($text, $separator, $enclosure, $ruleset_filename, $ruleset_name, &$errors) {
$rows = array();
$errors = array();
$table_html = null;
$separator = $this->getSeparatorChar($separator, $errors);
$enclosure = $this->getEnclosureChar($enclosure, $errors);
$this->parseInput($text, $separator, $enclosure, $rows);
if ($this->validateTableRows($rows, $errors)) {
$ruleset = $this->loadRuleset($ruleset_filename, $ruleset_name, $rows, $errors);
if (!empty($ruleset)) {
$table_html = $this->getFormattedTable($rows, $ruleset);
}
}
if (!empty($errors)) {
return null;
} else {
return $table_html;
}
}
function getSeparatorChar($code, &$errors) {
switch ($code) {
case SEPARATOR_COMMA: $char = ','; break;
case SEPARATOR_SEMICOLON: $char = ';'; break;
case SEPARATOR_SPACE: $char = ' '; break;
case SEPARATOR_TAB: $char = ' '; break;
case SEPARATOR_ASTERISK: $char = '*'; break;
case SEPARATOR_CARET: $char = '^'; break;
default: $errors[] = sprintf(JText::_('COM_TABULIZER_INVALID_SEPARATOR'),$code); $char = ','; break;
}
return $char;
}
function getEnclosureChar($code, &$errors) {
switch ($code) {
case ENCLOSURE_DOUBLE_QUOTES: $char = '"'; break;
case ENCLOSURE_SINGLE_QUOTES: $char = '\''; break;
case ENCLOSURE_NONE:
default: $char = ''; break;
}
return $char;
}
function loadRuleset($filename, $name, $rows, &$errors) {
# init ruleset
$ruleset = array('table'=>array(), 'rows'=>array(), 'columns' => array(), 'cells' => array(), 'suffix'=> '', 'style'=> '');
$num_of_rows = count($rows);
$num_of_columns = count($rows[1]);
$autospan_table = null; // this is used in combination with range_key
if ($name == 'none') {
return $ruleset;
}
# load all xml files in rules folder
$dir = $this->rules_dir;
$xmlfiles = array();
if (empty($filename)) {
# load all xml files in rules folder
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if (is_file($dir . $file)) {
if (preg_match('/'.XML_FILE_EXT.'$/i',$file)) {
$xmlfiles[] = $file;
}
}
}
closedir($dh);
}
}
} else {
# load sepcific xml file
if (file_exists($dir . $filename)) {
$xmlfiles[] = $filename;
}
}
if (empty($xmlfiles)) {
$errors[] = sprintf(JText::_('COM_TABULIZER_RULESET_FOLDER_EMPTY'),$dir);
return null;
}
# traverse each file to locate selected rule
$ruleset_found = false;
foreach ($xmlfiles as $xmlfile) {
$contents = file_get_contents($dir . $xmlfile);
if (empty($contents)) continue;
$p = xml_parser_create();
xml_parse_into_struct($p, $contents, $vals, $index);
xml_parser_free($p);
$ruleset_open = false;
$class_suffix = '';
$ruleset_style = '';
foreach ($vals as $node) {
switch ($node['tag']) {
case 'RULES':
if (!empty($node['attributes']['STYLE'])) {
$ruleset_style = trim($node['attributes']['STYLE']);
}
break;
case 'RULESET':
if ($node['type'] == 'open') {
if ($node['attributes']['NAME'] == $name) {
$ruleset_found = true;
$ruleset_open = true;
if (!empty($node['attributes']['SUFFIX'])) {
$class_suffix = trim($node['attributes']['SUFFIX']);
if (!empty($class_suffix)) $class_suffix = '-'.$class_suffix;
}
if (!empty($node['attributes']['STYLE'])) {
$ruleset_style = trim($node['attributes']['STYLE']);
}
}
} else if ($node['type'] == 'close') {
if ($ruleset_open) $ruleset_open = false;
} else if ($node['type'] == 'complete') {
if ($node['attributes']['NAME'] == $name) {
$ruleset_found = true;
if (!empty($node['attributes']['SUFFIX'])) {
$class_suffix = trim($node['attributes']['SUFFIX']);
if (!empty($class_suffix)) $class_suffix = '-'.$class_suffix;
}
if (!empty($node['attributes']['STYLE'])) {
$ruleset_style = trim($node['attributes']['STYLE']);
}
}
}
break;
case 'RULE':
if ($ruleset_open) {
if ($node['type'] == 'complete') {
$attributes = $node['attributes'];
$element = empty($attributes['ELEMENT'])?null:strtolower(trim($attributes['ELEMENT']));
if (!empty($element)) {
// verify element is acceptable
$acceptable_elements = array('table','row','column','cell');
if (!in_array($element, $acceptable_elements)) $element = null;
}
$range = empty($attributes['RANGE'])?null:trim($attributes['RANGE']);
// keep RANGE_COUNT for backward compatibility
$range_key = empty($attributes['RANGE_COUNT'])?0:intval(trim($attributes['RANGE_COUNT']));
$range_key = empty($attributes['RANGE_KEY'])?$range_key:intval(trim($attributes['RANGE_KEY']));
$set_attributes = array();
if (isset($attributes['ELEMENT_SECTION'])) $set_attributes['element_section'] = $attributes['ELEMENT_SECTION'];
if (isset($attributes['STYLE'])) $set_attributes['style'] = $attributes['STYLE'];
if (isset($attributes['AUTOSPAN'])) $set_attributes['autospan'] = $attributes['AUTOSPAN'];
if (isset($attributes['FORMAT'])) $set_attributes['format'] = $attributes['FORMAT'];
if (isset($attributes['REPLACEMENT'])) $set_attributes['replacement'] = $attributes['REPLACEMENT'];
if (isset($attributes['CALCULATION'])) $set_attributes['calculation'] = $attributes['CALCULATION'];
if (!empty($element) && !empty($range) && !empty($set_attributes)) {
$area = ($element == 'table')?$element:$element.'s';
if (!isset($ruleset[$area][$range])) {
$ruleset[$area][$range] = array($range_key => array());
}
if (!isset($ruleset[$area][$range][$range_key])) {
$ruleset[$area][$range][$range_key] = array();
}
$ruleset_entry = &$ruleset[$area][$range][$range_key];
foreach ($set_attributes as $attr_name => $attr_value) {
switch ($attr_name) {
case 'style':
if (!isset($ruleset_entry[$attr_name])) { $ruleset_entry[$attr_name] = $attr_value; } else { $ruleset_entry[$attr_name] .= ' ' . $attr_value; }
break;
case 'replacement':
if (!isset($ruleset_entry[$attr_name])) { $ruleset_entry[$attr_name] = array($attr_value); } else { $ruleset_entry[$attr_name][] = $attr_value; }
break;
case 'autospan':
$ruleset_entry[$attr_name] = 1;
break;
case 'format':
case 'calculation':
$ruleset_entry[$attr_name] = $attr_value;
break;
case 'element_section':
if ($element == 'row') $last = $num_of_columns;
else if ($element == 'column') $last = $num_of_rows;
else $last = 0; // ignore element section for elements "table" and "cell"
$section_ids = $this->getRangeIds($attr_value, 0, $last, null, null);
if (!isset($ruleset_entry[$attr_name])) { $ruleset_entry[$attr_name] = $section_ids; } else { $ruleset_entry[$attr_name] = array_intersect($ruleset_entry[$attr_name],$section_ids); }
break;
}
}
}
}
}
break;
}
}
if ($ruleset_found) break;
} // foreach xml files
if (!$ruleset_found) {
$errors[] = sprintf(JText::_('COM_TABULIZER_RULESET_NOT_FOUND'),$name);
return null;
}
// now convert ranges to actual ids
$rs = array('table'=> array(), 'rows' => array(), 'columns' => array(), 'cells'=> array(), 'suffix' => $class_suffix, 'style' => $ruleset_style );
// process table
$area = 'table';
$rs[$area] = array();
// to do ...
// process rows and columns
$areas = array('rows', 'columns');
foreach ($areas as $area) {
$last_var = 'num_of_' . $area;
$last = $$last_var;
foreach ($ruleset[$area] as $range => $range_rule) {
foreach ($range_rule as $range_key => $rule) {
if ($range_key && empty($autospan_table)) {
$autospan_table = array('rows' => array(), 'columns' => array());
$this->createAutospanTable($rows, $autospan_table);
}
$ids = $this->getRangeIds($range, $range_key, $last, $area, $autospan_table);
// if there is an element section, we need to transfer the row/column section to the "cells" area
if (!empty($rule['element_section'])) {
$section_ids = $rule['element_section'];
if ($area == 'rows') {
foreach ($ids as $id) {
foreach ($section_ids as $section_id) {
$cell_range = "{$id},{$section_id}";
if (!isset($ruleset['cells'][$cell_range])) {
$ruleset['cells'][$cell_range] = array(0 => array());
}
if (!isset($ruleset['cells'][$cell_range][0])) {
$ruleset['cells'][$cell_range][0] = array();
}
$ruleset['cells'][$cell_range][0] = $rule;
}
}
} else if ($area == 'columns') {
foreach ($ids as $id) {
foreach ($section_ids as $section_id) {
$cell_range = "{$section_id},{$id}";
if (!isset($ruleset['cells'][$cell_range])) {
$ruleset['cells'][$cell_range] = array(0 => array());
}
if (!isset($ruleset['cells'][$cell_range][0])) {
$ruleset['cells'][$cell_range][0] = array();
}
$ruleset['cells'][$cell_range][0] = $rule;
}
}
}
} else {
foreach ($ids as $id) {
if (!isset($rs[$area][$id])) {
$rs[$area][$id] = array();
foreach ($rule as $key => $value) {
$rs[$area][$id][$key] = $value;
}
} else {
foreach ($rule as $key => $value) {
if ($key == 'style') {
if (isset($rs[$area][$id][$key])) $rs[$area][$id][$key] .= ' ' . $value;
else $rs[$area][$id][$key] = $value;
} else if ($key == 'replacement') {
if (isset($rs[$area][$id][$key])) $rs[$area][$id][$key] = array_unique(array_merge($value, $rs[$area][$id][$key]));
else $rs[$area][$id][$key] = $value;
} else {
$rs[$area][$id][$key] = $value;
}
}
}
}
}
} // foreach $range_rule
}
}
// process cells
$area = 'cells';
$rs[$area] = array();
$search_values = array();
foreach ($ruleset[$area] as $range => $range_rule) {
foreach ($range_rule as $range_key => $rule) {
$ids = $this->getCellRangeIds($range, $rows);
if (!empty($ids)) {
foreach ($ids as $id) {
list($row_id,$column_id) = explode(',',$id);
if (!isset($rs[$area][$row_id][$column_id])) {
$rs[$area][$row_id][$column_id] = array();
foreach ($rule as $key => $value) {
$rs[$area][$row_id][$column_id][$key] = $value;
}
} else {
foreach ($rule as $key => $value) {
if ($key == 'style') {
if (isset($rs[$area][$row_id][$column_id][$key])) $rs[$area][$row_id][$column_id][$key] .= ' ' . $value;
else $rs[$area][$row_id][$column_id][$key] = $value;
} else if ($key == 'replacement') {
if (isset($rs[$area][$row_id][$column_id][$key])) $rs[$area][$row_id][$column_id][$key] = array_unique(array_merge($value,$rs[$area][$row_id][$column_id][$key]));
else $rs[$area][$row_id][$column_id][$key] = $value;
} else {
$rs[$area][$row_id][$column_id][$key] = $value;
}
}
}
}
}
} // foreach $range_rule
} // foreach $ruleset[$area] (area is cells)
return $rs;
}
/**
* Create a sample table to preview rules
*/
function previewRuleset($ruleset_filename, $ruleset_name, &$html, &$errors, $sample_data_text = null, $sample_data_sep = 'cm', $sample_data_enc = 'none') {
$table_text = '';
if (!empty($sample_data_text)) {
$table_text = $sample_data_text;
$separator = $sample_data_sep;
$enclosure = $sample_data_enc;
} else {
$num_of_rows = 10;
$num_of_columns = 5;
$separator = 'cm'; // comma
$enclosure = 'none';
$sep = ',';
for ($i=1;$i<=$num_of_rows;$i++) {
for ($j=1;$j<=$num_of_columns;$j++) {
if ($i==1) $cell = JText::_('COM_TABULIZER_COLUMN').' '. $j;
else if ($j ==1) $cell = JText::_('COM_TABULIZER_ROW').' '.$i;
else $cell = 10 - mt_rand(0,20);
if ($j<$num_of_columns) $cell .= $sep;
$table_text .= $cell;
}
$table_text .= "\n";
}
}
$this->setComments(true);
$html = $this->process($table_text, $separator, $enclosure, $ruleset_filename, $ruleset_name, $errors);
if (!empty($errors)) {
return false;
} else {
// remove include style/CSS directive
$pattern = TABULIZER_INCLUDE_STYLE_REGEX;
$replacement = '';
while (preg_match($pattern, $html, $regs, PREG_OFFSET_CAPTURE)) {
$html = substr_replace($html, $replacement, $regs[0][1], strlen($regs[0][0]));
}
return true;
}
} // end of previewRules
}
?>