1576 lines
37 KiB
PHP
1576 lines
37 KiB
PHP
<?php
|
|
class pivotState
|
|
{
|
|
/**
|
|
* Pivot state ID.
|
|
*
|
|
* @var int
|
|
* @access public
|
|
*/
|
|
public $id;
|
|
|
|
/**
|
|
* Pivot state dimension.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $dimension;
|
|
|
|
/**
|
|
* Pivot state group.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $group;
|
|
|
|
/**
|
|
* Pivot state code.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $code;
|
|
|
|
/**
|
|
* Pivot state driver.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $driver;
|
|
|
|
/**
|
|
* Pivot state mode.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $mode;
|
|
|
|
/**
|
|
* Pivot state name.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $name;
|
|
|
|
/**
|
|
* Pivot state names.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $names;
|
|
|
|
/**
|
|
* Pivot state description.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $desc;
|
|
|
|
/**
|
|
* Pivot state descriptions.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $descs;
|
|
|
|
/**
|
|
* Pivot state SQL.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $sql;
|
|
|
|
/**
|
|
* Pivot state fields.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $fields;
|
|
|
|
/**
|
|
* Pivot state fieldSettings.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $fieldSettings;
|
|
|
|
/**
|
|
* Pivot state relatedObject.
|
|
* e.g array('id' => 'action')
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $relatedObject;
|
|
|
|
/**
|
|
* Pivot state languages.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $langs;
|
|
|
|
/**
|
|
* client languages.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $clientLang;
|
|
|
|
/**
|
|
* Pivot state variables.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $vars;
|
|
|
|
/**
|
|
* Pivot state objects.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $objects;
|
|
|
|
/**
|
|
* Pivot state settings.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $settings;
|
|
|
|
/**
|
|
* Pivot state filters.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $filters;
|
|
|
|
/**
|
|
* Pivot state default drill.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $defaultDrill;
|
|
|
|
/**
|
|
* Pivot state drills.
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $drills;
|
|
|
|
/**
|
|
* Pivot state step.
|
|
*
|
|
* @var int
|
|
* @access public
|
|
*/
|
|
public $step;
|
|
|
|
/**
|
|
* Pivot state stage.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $stage;
|
|
|
|
/**
|
|
* Pivot state version.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $version;
|
|
|
|
/**
|
|
* Pivot state acl.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $acl;
|
|
|
|
/**
|
|
* Pivot state used.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $used;
|
|
|
|
/**
|
|
* Pivot state whitelist.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $whitelist;
|
|
|
|
/**
|
|
* Pivot stage action.
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $action = 'design';
|
|
|
|
/**
|
|
* error
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $error = false;
|
|
|
|
/**
|
|
* errorMsg
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $errorMsg = '';
|
|
|
|
/**
|
|
* queryCols
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $queryCols = array();
|
|
|
|
/**
|
|
* queryData
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $queryData = array();
|
|
|
|
/**
|
|
* pivotCols
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $pivotCols = array();
|
|
|
|
/**
|
|
* pivotData
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $pivotData = array();
|
|
|
|
/**
|
|
* pivotCellSpan
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $pivotCellSpan = array();
|
|
|
|
/**
|
|
* pivotFilters
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $pivotFilters = array();
|
|
|
|
/**
|
|
* pager
|
|
*
|
|
* @var int
|
|
* @access public
|
|
*/
|
|
public $pager;
|
|
|
|
/**
|
|
* sqlChanged
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $sqlChanged = false;
|
|
|
|
/**
|
|
* filterChanged.
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $filterChanged = false;
|
|
|
|
/**
|
|
* addQueryFilter
|
|
*
|
|
* @var array
|
|
* @access public
|
|
*/
|
|
public $addQueryFilter = array();
|
|
|
|
/**
|
|
* step2 finish with Sql, used to judge if step1 sql changed
|
|
*
|
|
* @var string
|
|
* @access public
|
|
*/
|
|
public $step2FinishSql = '';
|
|
|
|
/**
|
|
* First enter design.
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $firstEnterDesign = false;
|
|
|
|
/**
|
|
* Auto gen drills.
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $autoGenDrills = false;
|
|
|
|
/**
|
|
* Check step design.
|
|
*
|
|
* @var bool
|
|
* @access public
|
|
*/
|
|
public $checkStepDesign = false;
|
|
|
|
public $triggerQuery = false;
|
|
|
|
public $canChangeMode = true;
|
|
|
|
public $sqlbuilder = array();
|
|
|
|
/**
|
|
* __construct method.
|
|
*
|
|
* @param pivot object
|
|
* @param drills array
|
|
* @param clientLang string
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function __construct($pivot, $drills = array(), $clientLang = 'zh-cn', $sqlbuilder = array())
|
|
{
|
|
$this->id = $pivot->id;
|
|
$this->dimension = $pivot->dimension;
|
|
$this->group = $pivot->group;
|
|
$this->code = $pivot->code;
|
|
$this->driver = $pivot->driver;
|
|
$this->mode = $pivot->mode;
|
|
$this->name = $pivot->name;
|
|
$this->desc = $pivot->desc;
|
|
$this->names = $pivot->names;
|
|
$this->descs = $pivot->descs;
|
|
$this->sql = $pivot->sql;
|
|
$this->step = 'query';
|
|
$this->stage = $pivot->stage;
|
|
$this->version = $pivot->version;
|
|
$this->acl = $pivot->acl;
|
|
$this->whitelist = $pivot->whitelist;
|
|
|
|
$this->drills = $drills;
|
|
$this->defaultDrill = $this->initDrill();
|
|
|
|
$this->sqlbuilder = $sqlbuilder;
|
|
|
|
$this->fields = $this->json2Array($pivot->fieldSettings);
|
|
$this->langs = $this->json2Array($pivot->langs);
|
|
$this->vars = $this->json2Array($pivot->vars);
|
|
$this->objects = $this->json2Array($pivot->objects);
|
|
$this->settings = $this->json2Array($pivot->settings);
|
|
$this->filters = $this->json2Array($pivot->filters);
|
|
|
|
$this->clientLang = $clientLang;
|
|
$this->fieldSettings = array_merge_recursive($this->fields, $this->langs);
|
|
$this->setPager();
|
|
$this->formatSettingColumns();
|
|
$this->setStep2FinishSql();
|
|
}
|
|
|
|
/**
|
|
* Process query filters.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function processQueryFilters()
|
|
{
|
|
if($this->mode == 'text') return;
|
|
|
|
$querys = $this->sqlbuilder->querys;
|
|
$this->clearFilters();
|
|
if(empty($querys)) return;
|
|
|
|
if($this->sqlbuilder->checkQuerys() !== true) return;
|
|
|
|
foreach($querys as $index => $query)
|
|
{
|
|
$filter = $this->getDefaultQueryFilter();
|
|
$field = "var$index";
|
|
foreach(array_keys($filter) as $key)
|
|
{
|
|
if($key == 'field') $filter[$key] = $field;
|
|
elseif(isset($query[$key])) $filter[$key] = $query[$key];
|
|
}
|
|
$filter['from'] = 'query';
|
|
$this->filters[] = $filter;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Match field setting from builder.
|
|
*
|
|
* @param string $key
|
|
* @param array $setting
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function matchFieldSettingFromBuilder($key, $setting)
|
|
{
|
|
if($this->mode == 'text') return $setting;
|
|
$selects = array_merge($this->sqlbuilder->getSelects(), $this->sqlbuilder->getFuncSelects());
|
|
foreach($selects as $select)
|
|
{
|
|
list($table, $field, $alias) = $select;
|
|
if($key != $alias) continue;
|
|
|
|
$fieldList = $this->sqlbuilder->getTableDescList($table);
|
|
$name = zget($fieldList, $field, $field);
|
|
$setting[$this->clientLang] = $name;
|
|
$setting['field'] = $field;
|
|
}
|
|
return $setting;
|
|
}
|
|
|
|
/**
|
|
* Clear fieldSettings.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function clearFieldSettings()
|
|
{
|
|
$this->fields = array();
|
|
$this->langs = array();
|
|
$this->fieldSettings = array();
|
|
$this->relatedObject = array();
|
|
}
|
|
|
|
/**
|
|
* Clear settings.
|
|
*
|
|
* @param int $init
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function clearSettings($init = false)
|
|
{
|
|
$this->settings = array();
|
|
if($init) $this->completeSettings();
|
|
}
|
|
|
|
/**
|
|
* Clear column drill.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function clearColumnDrill()
|
|
{
|
|
if(empty($this->settings)) return;
|
|
if(!isset($this->settings['columns']) || empty($this->settings['columns'])) return;
|
|
|
|
$columns = $this->settings['columns'];
|
|
foreach($columns as $index => $column)
|
|
{
|
|
if(isset($column['drill'])) unset($this->settings['columns'][$index]['drill']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear filters.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function clearFilters()
|
|
{
|
|
$this->filters = array();
|
|
$this->pivotFilters = array();
|
|
}
|
|
|
|
/**
|
|
* Clear drills.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function clearDrills()
|
|
{
|
|
$this->drills = array();
|
|
}
|
|
|
|
/**
|
|
* Sql changed.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function sqlChanged()
|
|
{
|
|
$this->queryCols = array();
|
|
$this->queryData = array();
|
|
}
|
|
|
|
/**
|
|
* Get filters.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getFilters()
|
|
{
|
|
$filters = array();
|
|
$filterValues = array();
|
|
|
|
if(!empty($this->pivotFilters))
|
|
{
|
|
$pivotFilters = array();
|
|
foreach($this->pivotFilters as $pivotFilter) $pivotFilters = array_merge($pivotFilters, $pivotFilter);
|
|
foreach($pivotFilters as $pivotFilter) $filterValues[$pivotFilter['name']] = $pivotFilter['value'];
|
|
}
|
|
|
|
foreach($this->filters as $filter)
|
|
{
|
|
$value = zget($filterValues, $filter['field'], $filter['default']);
|
|
if(is_array($value)) $value = array_filter($value);
|
|
if(isset($filterValues[$filter['field']])) $filter['default'] = $value;
|
|
$filters[$filter['field']] = $filter;
|
|
}
|
|
|
|
return $filters;
|
|
}
|
|
|
|
/**
|
|
* Add filter.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function addFilter()
|
|
{
|
|
$firstKey = key($this->fieldSettings);
|
|
$firstField = current($this->fieldSettings);
|
|
$lang = $this->clientLang;
|
|
|
|
$this->filters[] = array('field' => $firstKey, 'saveAs' => '', 'type' => 'input', 'name' => $firstField[$lang], 'default' => '');
|
|
}
|
|
|
|
/**
|
|
* Judge is query filter or not.
|
|
*
|
|
* @param array $filters
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isQueryFilter($filters = array())
|
|
{
|
|
$filters = empty($filters) ? $this->filters : $filters;
|
|
if(empty($filters)) return false;
|
|
$filter = current($filters);
|
|
|
|
return isset($filter['from']) && $filter['from'] == 'query';
|
|
}
|
|
|
|
/**
|
|
* Save query filter.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function saveQueryFilter()
|
|
{
|
|
$filter = $this->addQueryFilter;
|
|
$filter['from'] = 'query';
|
|
$this->filters[] = $filter;
|
|
$this->addQueryFilter = array();
|
|
}
|
|
|
|
/**
|
|
* Add variable to sql.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function addVariableToSql()
|
|
{
|
|
$variable = $this->addQueryFilter['field'];
|
|
|
|
$this->sql .= "\$$variable";
|
|
}
|
|
|
|
/**
|
|
* Complete filters default.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function completeFiltersDefault()
|
|
{
|
|
$queryDefaults = array('select' => '', 'input' => '', 'date' => '', 'datetime' => '');
|
|
$resultDefaults = array('select' => array(), 'input' => '', 'date' => array('begin' => '', 'end' => ''), 'datetime' => array('begin' => '', 'end' => ''));
|
|
foreach($this->filters as $index => $filter)
|
|
{
|
|
if(isset($filter['default'])) continue;
|
|
|
|
$from = zget($filter, 'from', 'result');
|
|
$type = $filter['type'];
|
|
$defaults = $from == 'query' ? $queryDefaults : $resultDefaults;
|
|
|
|
$filter['default'] = $defaults[$type];
|
|
$this->filters[$index] = $filter;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert filters to where conditions.
|
|
*
|
|
* @param array $filters
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function convertFiltersToWhere($filters)
|
|
{
|
|
if($this->isQueryFilter($filters)) return array_values($filters);
|
|
|
|
$filterWheres = array();
|
|
foreach($filters as $filter)
|
|
{
|
|
$field = $filter['field'];
|
|
$default = zget($filter, 'default', '');
|
|
$type = $filter['type'];
|
|
|
|
if(empty($default)) continue;
|
|
|
|
switch($type)
|
|
{
|
|
case 'select':
|
|
if(is_string($default) && strpos($default, ',') !== false) $default = explode(',', $default);
|
|
if(is_array($default)) $default = implode("', '", array_filter($default, function($val){return trim($val) != '';}));
|
|
if(empty($default)) break;
|
|
$value = "('" . $default . "')";
|
|
$filterWheres[$field] = array('operator' => 'IN', 'type' => $type, 'value' => $value);
|
|
break;
|
|
case 'input':
|
|
$filterWheres[$field] = array('operator' => 'LIKE', 'type' => $type, 'value' => "'%$default%'");
|
|
break;
|
|
case 'date':
|
|
case 'datetime':
|
|
$begin = $default['begin'];
|
|
$end = $default['end'];
|
|
|
|
if(!empty($begin)) $begin = date('Y-m-d 00:00:00', strtotime($begin));
|
|
if(!empty($end)) $end = date('Y-m-d 23:59:59', strtotime($end));
|
|
|
|
if(!empty($begin) && empty($end)) $filterWheres[$field] = array('operator' => '>=', 'type' => $type, 'value' => "'{$begin}'");
|
|
if( empty($begin) && !empty($end)) $filterWheres[$field] = array('operator' => '<=', 'type' => $type, 'value' => "'{$end}'");
|
|
if(!empty($begin) && !empty($end)) $filterWheres[$field] = array('operator' => 'BETWEEN', 'type' => $type, 'value' => "'{$begin}' AND '{$end}'");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $filterWheres;
|
|
}
|
|
|
|
/**
|
|
* Set filters default value.
|
|
*
|
|
* @param array $filterValues
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setFiltersDefaultValue($filterValues)
|
|
{
|
|
$filters = array();
|
|
foreach($this->filters as $index => $filter)
|
|
{
|
|
if(!isset($filterValues[$index])) continue;
|
|
|
|
$default = $filterValues[$index];
|
|
$type = $filter['type'];
|
|
$from = zget($filter, 'from', 'result');
|
|
if($type == 'select' && is_array($default)) $default = array_filter($default);
|
|
if($type == 'date' || $type == 'datetime')
|
|
{
|
|
if($from == 'query')
|
|
{
|
|
$format = $type == 'datetime' ? 'Y-m-d H:i:s' : 'Y-m-d';
|
|
switch($default)
|
|
{
|
|
case '$MONDAY': $default = date($format, time() - (date('N') - 1) * 24 * 3600); break;
|
|
case '$SUNDAY': $default = date($format, time() + (7 - date('N')) * 24 * 3600); break;
|
|
case '$MONTHBEGIN': $default = date($format, time() - (date('j') - 1) * 24 * 3600); break;
|
|
case '$MONTHEND': $default = date($format, time() + (date('t') - date('j')) * 24 * 3600); break;
|
|
default:
|
|
if(is_numeric($default)) $default = date('Y-m-d H:i:s', $default / 1000);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(is_array($default))
|
|
{
|
|
$begin = $default['begin'];
|
|
$end = $default['end'];
|
|
|
|
if(is_numeric($begin)) $begin = date('Y-m-d H:i:s', $begin / 1000);
|
|
if(is_numeric($end)) $end = date('Y-m-d H:i:s', $end / 1000);
|
|
|
|
$default = array('begin' => $begin, 'end' => $end);
|
|
}
|
|
else
|
|
{
|
|
$default = array('begin' => '', 'end' => '');
|
|
}
|
|
}
|
|
}
|
|
$filter['default'] = $default;
|
|
$filters[] = $filter;
|
|
}
|
|
|
|
return $filters;
|
|
}
|
|
|
|
/**
|
|
* Complete settings.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function isSummaryNotUse()
|
|
{
|
|
return (isset($this->settings['summary']) && $this->settings['summary'] === 'notuse');
|
|
}
|
|
|
|
/**
|
|
* Complete settings.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function completeSettings()
|
|
{
|
|
if($this->isSummaryNotUse())
|
|
{
|
|
$this->settings['drills'] = array_column($this->drills, 'condition', 'field');
|
|
return;
|
|
}
|
|
|
|
$settings = $this->settings;
|
|
if(!isset($settings['summary']) || $settings['summary'] !== 'notuse') $this->settings['summary'] = 'use';
|
|
if(!isset($settings['group1'])) $this->settings['group1'] = '';
|
|
if(!isset($settings['columns']) || empty($settings['columns'])) $this->addColumn();
|
|
if(!isset($settings['columnTotal'])) $this->settings['columnTotal'] = 'noShow';
|
|
if(!isset($settings['columnPosition'])) $this->settings['columnPosition'] = 'bottom';
|
|
|
|
foreach($this->settings['columns'] as $index => $column)
|
|
{
|
|
$this->settings['columns'][$index] = array_merge($this->getDefaultColumn(), $column);
|
|
|
|
unset($this->settings['columns'][$index]['drill']);
|
|
foreach($this->drills as $drill)
|
|
{
|
|
if(empty($drill)) continue;
|
|
if($drill['field'] == $column['field']) $this->settings['columns'][$index]['drill'] = $drill;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process column show origin.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function processColumnShowOrigin()
|
|
{
|
|
if(empty($this->settings['columns'])) return;
|
|
|
|
$columns = $this->settings['columns'];
|
|
foreach($columns as $index => $column)
|
|
{
|
|
$showOrigin = $column['showOrigin'];
|
|
$defaultColumn = $this->getDefaultColumn();
|
|
$columns[$index] = $showOrigin ? array('field' => $column['field'], 'showOrigin' => 1) : array_merge($defaultColumn, $column);
|
|
}
|
|
|
|
$this->settings['columns'] = $columns;
|
|
}
|
|
|
|
/**
|
|
* Get field options.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getFieldOptions()
|
|
{
|
|
$options = array();
|
|
$lang = $this->clientLang;
|
|
foreach($this->fieldSettings as $field => $settings)
|
|
{
|
|
$name = zget($settings, 'name', $field);
|
|
$text = zget($settings, $lang, $name);
|
|
$options[] = array('text' => $text, 'value' => $field, 'key' => $field);
|
|
}
|
|
|
|
return $options;
|
|
}
|
|
|
|
/**
|
|
* Get setting groups.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getSettingGroups()
|
|
{
|
|
$groups = array();
|
|
$settings = $this->settings;
|
|
$keys = array_keys($settings);
|
|
foreach($keys as $key) if(strpos($key, 'group') === 0) $groups[$key] = $settings[$key];
|
|
|
|
return $groups;
|
|
}
|
|
|
|
/**
|
|
* Get setting columns.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getSettingColumns()
|
|
{
|
|
return $this->settings['columns'];
|
|
}
|
|
|
|
/**
|
|
* Add column.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function addColumn()
|
|
{
|
|
$this->settings['columns'][] = $this->getDefaultColumn();
|
|
}
|
|
|
|
/**
|
|
* Init drill.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function initDrill()
|
|
{
|
|
return array('field' => '', 'object' => '', 'referSQL' => '', 'whereSQL' => '', 'type' => 'manual', 'condition' => array($this->addCondition()));
|
|
}
|
|
|
|
/**
|
|
* Add drill.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function addDrill($drill)
|
|
{
|
|
$this->drills[] = $drill;
|
|
}
|
|
|
|
/**
|
|
* Add condition.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function addCondition()
|
|
{
|
|
return array('drillObject' => '', 'drillAlias' => '', 'drillField' => '', 'queryField' => '');
|
|
}
|
|
|
|
/**
|
|
* Get default column.
|
|
*
|
|
* @param string|null $field
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function getDefaultColumn($field = null)
|
|
{
|
|
if(empty($field))
|
|
{
|
|
$field = key($this->fieldSettings);
|
|
}
|
|
|
|
return array('field' => $field, 'slice' => 'noSlice', 'stat' => 'count', 'showTotal' => 'noShow', 'showMode' => 'default', 'monopolize' => 0, 'showOrigin' => 0);
|
|
}
|
|
|
|
/**
|
|
* Get default query filter.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function getDefaultQueryFilter()
|
|
{
|
|
return array('field' => '', 'name' => '', 'type' => 'input', 'typeOption' => '', 'default' => '', 'items' => array());
|
|
}
|
|
|
|
/**
|
|
* Update from $_POST.
|
|
*
|
|
* @param array $post
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function updateFromPost($post)
|
|
{
|
|
if(!isset($post['data'])) return;
|
|
|
|
$data = json_decode($post['data'], true);
|
|
foreach($data as $key => $value)
|
|
{
|
|
if(!empty($value['sql'])) $value['sql'] = base64_encode($value['sql']);
|
|
$this->$key = $key == 'sql' ? base64_decode($value) : $value;
|
|
}
|
|
|
|
$this->formatSettingColumns();
|
|
$this->processFieldSettingsLang();
|
|
$this->completeFiltersDefault();
|
|
$this->canChangeMode = $this->setCanChangeMode();
|
|
}
|
|
|
|
/**
|
|
* Set can change mode.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function setCanChangeMode()
|
|
{
|
|
if($this->mode == 'builder') return true;
|
|
if($this->mode == 'text' && empty($this->sql)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Update from cache.
|
|
*
|
|
* @param object $cache
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function updateFromCache($cache)
|
|
{
|
|
if($cache === false) return;
|
|
foreach($cache as $key => $value)
|
|
{
|
|
if(is_array($value) || is_object($value)) $value = json_decode(json_encode($value), true);
|
|
$this->$key = $value;
|
|
}
|
|
|
|
$this->formatSettingColumns();
|
|
$this->processFieldSettingsLang();
|
|
$this->completeFiltersDefault();
|
|
$this->canChangeMode = $this->setCanChangeMode();
|
|
}
|
|
|
|
/**
|
|
* Format setting columns.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function formatSettingColumns()
|
|
{
|
|
if(empty($this->settings->columns)) return;
|
|
|
|
foreach($this->settings->columns as $id => $column)
|
|
{
|
|
$column['monopolize'] = (int)$column['monopolize'];
|
|
$column['showOrigin'] = (int)$column['showOrigin'];
|
|
|
|
$this->settings->columns[$id] = $column;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear properies before query sql.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function beforeQuerySql()
|
|
{
|
|
$this->error = false;
|
|
$this->errorMsg = '';
|
|
$this->queryCols = array();
|
|
$this->queryData = array();
|
|
$this->pivotCols = array();
|
|
$this->pivotData = array();
|
|
$this->pivotCellSpan = array();
|
|
}
|
|
|
|
/**
|
|
* Set fieldSettings with merge.
|
|
*
|
|
* @param array $settings
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setFieldSettings($settings)
|
|
{
|
|
$settings = (array)$settings;
|
|
$oldFieldSettings = !empty($this->fieldSettings) ? $this->fieldSettings : array();
|
|
$newFieldSettings = array();
|
|
|
|
foreach($settings as $field => $setting)
|
|
{
|
|
$oldSetting = isset($oldFieldSettings[$field]) ? $oldFieldSettings[$field] : array();
|
|
if(!empty($oldSetting))
|
|
{
|
|
$newFieldSettings[$field] = $this->processFieldSettingLang($field, $oldSetting, $setting);
|
|
|
|
if($setting['type'] != $oldSetting['type'] && in_array($setting['type'], array('user', 'type'))) $newFieldSettings[$field]['type'] = $setting['type'];
|
|
}
|
|
else
|
|
{
|
|
// $newFieldSettings[$field] = $setting;
|
|
$newFieldSettings[$field] = $this->matchFieldSettingFromBuilder($field, $setting);
|
|
}
|
|
}
|
|
|
|
$this->fields = $this->json2Array($newFieldSettings);
|
|
$this->fieldSettings = $newFieldSettings;
|
|
}
|
|
|
|
/**
|
|
* Set drills.
|
|
*
|
|
* @param array $drills
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setDrills($drills)
|
|
{
|
|
$this->drills = json_decode(json_encode($drills), true);
|
|
}
|
|
|
|
/**
|
|
* Set filters.
|
|
*
|
|
* @param array $drills
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setFilters($filters)
|
|
{
|
|
$this->filters = json_decode(json_encode($filters), true);
|
|
}
|
|
|
|
/**
|
|
* Set field related object.
|
|
*
|
|
* @param array $relatedObject
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setFieldRelatedObject($relatedObject)
|
|
{
|
|
$this->relatedObject = $relatedObject;
|
|
}
|
|
|
|
/**
|
|
* Set step2 finishsql.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setStep2FinishSql()
|
|
{
|
|
if($this->issetSettings()) $this->step2FinishSql = $this->sql;
|
|
}
|
|
|
|
/**
|
|
* isset pivot setting.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function issetSettings()
|
|
{
|
|
if($this->isSummaryNotUse()) return true;
|
|
|
|
if(empty($this->getSettingGroups())) return false;
|
|
$columns = $this->getSettingColumns();
|
|
if(count($columns) == 1 && empty($columns[0]['field'])) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Process fieldSettings lang.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function processFieldSettingsLang()
|
|
{
|
|
if(empty($this->fieldSettings)) return;
|
|
foreach($this->fieldSettings as $field => $fieldSetting)
|
|
{
|
|
$this->fieldSettings[$field] = $this->processFieldSettingLang($field, $fieldSetting);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process fieldSetting lang.
|
|
*
|
|
* @param string $field
|
|
* @param array $fieldSetting
|
|
* @param array $newSetting
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function processFieldSettingLang($field, $oldSetting, $newSetting = array())
|
|
{
|
|
$lang = $this->clientLang;
|
|
if(!empty($oldSetting[$lang])) return $oldSetting;
|
|
|
|
if(!empty($newSetting[$lang]))
|
|
{
|
|
$oldSetting[$lang] = $newSetting[$lang];
|
|
return $oldSetting;
|
|
}
|
|
|
|
$oldSetting[$lang] = isset($oldSetting['name']) ? $oldSetting['name'] : $field;
|
|
return $oldSetting;
|
|
}
|
|
|
|
/**
|
|
* Build cols for query sql with lang.
|
|
*
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public function buildQuerySqlCols()
|
|
{
|
|
$cols = array();
|
|
$lang = $this->clientLang;
|
|
foreach($this->fieldSettings as $field => $settings)
|
|
{
|
|
$settings = (array)$settings;
|
|
$title = isset($settings[$lang]) ? $settings[$lang] : $field;
|
|
|
|
$cols[] = array('name' => $field, 'title' => $title, 'sortType' => false);
|
|
}
|
|
|
|
$this->queryCols = $cols;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get langs.
|
|
*
|
|
* @param string $type
|
|
* @access public
|
|
* @return object|string
|
|
*/
|
|
public function getFields($type = 'object')
|
|
{
|
|
$fieldSettings = $this->fieldSettings;
|
|
|
|
if(empty($fieldSettings)) return null;
|
|
|
|
$fields = array();
|
|
$keys = array('object', 'field', 'type');
|
|
foreach($fieldSettings as $fieldKey => $fieldSetting)
|
|
{
|
|
$field = array();
|
|
foreach($keys as $key)
|
|
{
|
|
if(isset($fieldSetting[$key])) $field[$key] = $fieldSetting[$key];
|
|
}
|
|
|
|
$fields[$fieldKey] = $field;
|
|
}
|
|
return $type == 'object' ? $fields : json_encode($fields);
|
|
}
|
|
|
|
/**
|
|
* Get langs.
|
|
*
|
|
* @param string $type
|
|
* @access public
|
|
* @return object|string
|
|
*/
|
|
public function getLangs($type = 'object')
|
|
{
|
|
$fieldSettings = $this->fieldSettings;
|
|
|
|
if(empty($fieldSettings)) return null;
|
|
|
|
$langs = array();
|
|
$keys = array('object', 'field', 'type');
|
|
foreach($fieldSettings as $fieldKey => $fieldSetting)
|
|
{
|
|
$lang = array();
|
|
foreach($fieldSetting as $key => $value)
|
|
{
|
|
if(!in_array($key, $keys)) $lang[$key] = $value;
|
|
}
|
|
|
|
$langs[$fieldKey] = $lang;
|
|
}
|
|
|
|
return $type == 'object' ? $langs : json_encode($langs);
|
|
}
|
|
|
|
/**
|
|
* Get filters.
|
|
*
|
|
* @param string $type
|
|
* @access public
|
|
* @return object|string
|
|
*/
|
|
public function getFiltersForSave($type = 'object')
|
|
{
|
|
$filters = $this->filters;
|
|
foreach($filters as $index => $filter)
|
|
{
|
|
if(isset($filter['items'])) unset($filters[$index]['items']);
|
|
}
|
|
if($type == 'object') return $filters;
|
|
return json_encode($filters);
|
|
}
|
|
|
|
/**
|
|
* Judge is queried.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isQueried()
|
|
{
|
|
return !empty($this->sql) && !$this->isError() && !empty($this->queryCols);
|
|
}
|
|
|
|
/**
|
|
* Check fields with setting.
|
|
*
|
|
* @param bool $removeUnused
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function checkFieldsWithSetting($removeUnused = false)
|
|
{
|
|
$settings = $this->settings;
|
|
$fields = $this->fieldSettings;
|
|
|
|
$isChanged = false;
|
|
foreach($settings as $key => $value)
|
|
{
|
|
if(strpos($key, 'group') === 0 && !isset($fields[$value]))
|
|
{
|
|
$isChanged = true;
|
|
if($removeUnused) unset($this->settings[$key]);
|
|
}
|
|
if($key === 'columns')
|
|
{
|
|
foreach($value as $index => $column)
|
|
{
|
|
if(!isset($fields[$column['field']]) || !isset($fields[$column['slice']]))
|
|
{
|
|
$isChanged = true;
|
|
if($removeUnused) unset($this->settings['columns'][$index]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$filters = $this->filters;
|
|
foreach($filters as $index => $filter)
|
|
{
|
|
$from = zget($filter, 'from', 'result');
|
|
if($from == 'query') continue;
|
|
if(!isset($fields[$filter['field']]))
|
|
{
|
|
$isChanged = true;
|
|
if($removeUnused) unset($this->filters[$index]);
|
|
}
|
|
}
|
|
|
|
$drills = $this->drills;
|
|
foreach($drills as $index => $drill)
|
|
{
|
|
if(!isset($fields[$drill['field']]))
|
|
{
|
|
$isChanged = true;
|
|
if($removeUnused) unset($this->drills[$index]);
|
|
}
|
|
foreach($drill['condition'] as $conditionIndex => $condition)
|
|
{
|
|
if(!isset($fields[$condition['queryField']]))
|
|
{
|
|
$isChanged = true;
|
|
if($removeUnused) unset($this->drills[$index]['condition'][$conditionIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if($removeUnused) $this->completeSettings();
|
|
|
|
return $isChanged;
|
|
}
|
|
|
|
/**
|
|
* Check settings.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function checkSettings()
|
|
{
|
|
if($this->isSummaryNotUse()) return array();
|
|
|
|
$errors = array();
|
|
foreach($this->settings as $key => $value)
|
|
{
|
|
if(strpos($key, 'group') === 0 && empty($value))
|
|
{
|
|
$errors[$key] = true;
|
|
continue;
|
|
}
|
|
|
|
if($key === 'columns')
|
|
{
|
|
foreach($value as $index => $column)
|
|
{
|
|
if(empty($column['field'])) $errors[$key][$index]['field'] = true;
|
|
if($column['showOrigin'] === 0 && empty($column['stat'])) $errors[$key][$index]['stat'] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* Check query filter.
|
|
*
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
public function checkQueryFilter()
|
|
{
|
|
$errors = array();
|
|
foreach($this->filters as $index => $filter)
|
|
{
|
|
if(empty($filter['field'])) $errors[$index]['field'] = true;
|
|
if(empty($filter['name'])) $errors[$index]['name'] = true;
|
|
}
|
|
|
|
$addFilter = $this->addQueryFilter;
|
|
if(empty($addFilter['field'])) $errors[$index]['field'] = true;
|
|
if(empty($addFilter['name'])) $errors[$index]['name'] = true;
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* Match query filte from sql.
|
|
*
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function matchQueryFilterFromSql()
|
|
{
|
|
if(!$this->isQueryFilter()) return;
|
|
|
|
$keepFilters = array();
|
|
$keepPivotFilters = array();
|
|
foreach($this->filters as $index => $filter)
|
|
{
|
|
$field = $filter['field'];
|
|
if(strpos($this->sql, "\$$field") !== false)
|
|
{
|
|
$keepFilters[] = $filter;
|
|
$keepPivotFilters[] = $this->pivotFilters[0][$index];
|
|
}
|
|
}
|
|
|
|
$this->filters = $keepFilters;
|
|
$this->pivotFilters[0] = $keepPivotFilters;
|
|
}
|
|
|
|
/**
|
|
* Set action.
|
|
*
|
|
* @param string $action
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setAction($action)
|
|
{
|
|
if($action == 'enterDesign') $action = 'design';
|
|
$this->action = $action;
|
|
}
|
|
|
|
/**
|
|
* Set step.
|
|
*
|
|
* @param int $step
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setStep($step)
|
|
{
|
|
$this->step = $step;
|
|
}
|
|
|
|
/**
|
|
* Judge is publish action.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isPublish()
|
|
{
|
|
return $this->action == 'publish';
|
|
}
|
|
|
|
/**
|
|
* Judge is design action.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isDesign()
|
|
{
|
|
return $this->action == 'design';
|
|
}
|
|
|
|
/**
|
|
* Judge is first design action.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isFirstDesign()
|
|
{
|
|
return $this->isDesign() && empty($this->sql);
|
|
}
|
|
|
|
/**
|
|
* Judge is error.
|
|
*
|
|
* @access public
|
|
* @return bool
|
|
*/
|
|
public function isError()
|
|
{
|
|
return $this->error;
|
|
}
|
|
|
|
/**
|
|
* Get error message.
|
|
*
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function getError()
|
|
{
|
|
return $this->errorMsg;
|
|
}
|
|
|
|
/**
|
|
* Set error.
|
|
*
|
|
* @param string $msg
|
|
* @access public
|
|
* @return object
|
|
*/
|
|
public function setError($msg)
|
|
{
|
|
$this->error = true;
|
|
$this->errorMsg = $msg;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set pager
|
|
*
|
|
* @param int $total
|
|
* @param int $recPerPage
|
|
* @param int $pageID
|
|
* @access public
|
|
* @return void
|
|
*/
|
|
public function setPager($total = 0, $recPerPage = 10, $pageID = 1)
|
|
{
|
|
$this->pager = array();
|
|
$this->pager['total'] = $total;
|
|
$this->pager['recPerPage'] = $recPerPage;
|
|
$this->pager['pageID'] = $pageID;
|
|
$this->pager['pageTotal'] = $total % $recPerPage == 0 ? (int)($total / $recPerPage) : (int)($total / $recPerPage) + 1;
|
|
}
|
|
|
|
/**
|
|
* Convert json string to array.
|
|
*
|
|
* @param string|object|array|null $json
|
|
* @access public
|
|
* @return array
|
|
*/
|
|
private function json2Array(string|object|array|null $json): array
|
|
{
|
|
if(empty($json)) return array();
|
|
if(is_string($json)) return json_decode($json, true);
|
|
if(is_object($json) || is_array($json)) return json_decode(json_encode($json), true);
|
|
|
|
return $json;
|
|
}
|
|
}
|