|
<?php defined('SYSPATH') or die('No direct script access.');
|
|
/*
|
|
* This file is part of open source system FreeNetIS
|
|
* and it is released under GPLv3 licence.
|
|
*
|
|
* More info about licence can be found:
|
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
|
*
|
|
* More info about project can be found:
|
|
* http://www.freenetis.org/
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* This is library for filter form
|
|
*
|
|
* @author Michal Kliment
|
|
* @version 1.0
|
|
*/
|
|
class Filter_form
|
|
{
|
|
/**
|
|
* Template to show filter form
|
|
* @var string
|
|
*/
|
|
protected $template = 'filter_form_template';
|
|
|
|
/**
|
|
* Array of all filters
|
|
* @var array
|
|
*/
|
|
protected $filters = array();
|
|
|
|
/**
|
|
* Array of all filter's values
|
|
* @var array
|
|
*/
|
|
protected $values = array();
|
|
|
|
/**
|
|
* Array of all filter's types
|
|
* @var array
|
|
*/
|
|
protected $types = array();
|
|
|
|
/**
|
|
* Array of all filter's operations
|
|
* @var array
|
|
*/
|
|
protected $operations = array();
|
|
|
|
/**
|
|
* Array of all filter's tables
|
|
* @var array
|
|
*/
|
|
protected $tables = array();
|
|
|
|
/**
|
|
* Array of boolean values whether filter is default
|
|
* @var array
|
|
*/
|
|
protected $default = array();
|
|
|
|
/**
|
|
* Count of default filters
|
|
* @var integer
|
|
*/
|
|
protected $default_count = 0;
|
|
|
|
/**
|
|
* Definition of constants
|
|
*/
|
|
const OPER_CONTAINS = 1;
|
|
const OPER_CONTAINS_NOT = 2;
|
|
const OPER_IS = 3;
|
|
const OPER_IS_NOT = 4;
|
|
const OPER_EQUAL = 5;
|
|
const OPER_EQUAL_NOT = 6;
|
|
const OPER_SMALLER = 7;
|
|
const OPER_SMALLER_OR_EQUAL = 8;
|
|
const OPER_GREATER = 9;
|
|
const OPER_GREATER_OR_EQUAL = 10;
|
|
const OPER_BIT_IS = 11;
|
|
const OPER_BIT_IS_NOT = 12;
|
|
const OPER_NETWORK_IS_IN = 13;
|
|
const OPER_NETWORK_IS_NOT_IN = 14;
|
|
const OPER_IS_EMPTY = 15;
|
|
const OPER_IS_NOT_EMPTY = 16;
|
|
|
|
/**
|
|
* Array with definition of all operations
|
|
* @var array
|
|
*/
|
|
protected $opers = array
|
|
(
|
|
self::OPER_CONTAINS => array
|
|
(
|
|
'name' => 'contains',
|
|
'sql' => "LIKE '%{VALUE}%' COLLATE utf8_general_ci",
|
|
),
|
|
self::OPER_CONTAINS_NOT => array
|
|
(
|
|
'name' => 'contains not',
|
|
'sql' => "NOT LIKE '%{VALUE}%' COLLATE utf8_general_ci",
|
|
),
|
|
self::OPER_IS => array
|
|
(
|
|
'name' => 'is',
|
|
'sql' => "LIKE '{VALUE}' COLLATE utf8_general_ci"
|
|
),
|
|
self::OPER_IS_NOT => array
|
|
(
|
|
'name' => 'is not',
|
|
'sql' => "NOT LIKE '{VALUE}' COLLATE utf8_general_ci" ,
|
|
),
|
|
self::OPER_EQUAL => array
|
|
(
|
|
'name' => '=',
|
|
'sql' => "= '{VALUE}'",
|
|
),
|
|
self::OPER_EQUAL_NOT => array
|
|
(
|
|
'name' => '!=',
|
|
'sql' => "<> '{VALUE}'",
|
|
),
|
|
self::OPER_SMALLER => array
|
|
(
|
|
'name' => '<',
|
|
'sql' => "< '{VALUE}'",
|
|
),
|
|
self::OPER_SMALLER_OR_EQUAL => array
|
|
(
|
|
'name' => '<=',
|
|
'sql' => "<= '{VALUE}'",
|
|
),
|
|
self::OPER_GREATER => array
|
|
(
|
|
'name' => '>',
|
|
'sql' => "> '{VALUE}'",
|
|
),
|
|
self::OPER_GREATER_OR_EQUAL => array
|
|
(
|
|
'name' => '>=',
|
|
'sql' => ">= '{VALUE}'",
|
|
),
|
|
self::OPER_BIT_IS => array
|
|
(
|
|
'name' => 'is',
|
|
'sql' => "& {VALUE} > 0",
|
|
),
|
|
self::OPER_BIT_IS_NOT => array
|
|
(
|
|
'name' => 'is not',
|
|
'sql' => "& {VALUE} = 0",
|
|
),
|
|
self::OPER_NETWORK_IS_IN => array
|
|
(
|
|
'name' => 'is in',
|
|
'pattern' => '/^(?P<VALUE1>((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9]))\/(?P<VALUE2>(3[0-2])|(2[0-9])|(1[0-9])|([0-9]))$/',
|
|
'sql' => "& (0xffffffff<<(32-{VALUE2}) & 0xffffffff) = inet_aton('{VALUE1}')",
|
|
'function' => 'inet_aton'
|
|
),
|
|
self::OPER_NETWORK_IS_NOT_IN => array
|
|
(
|
|
'name' => 'is not in',
|
|
'pattern' => '/^(?P<VALUE1>((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9])\.((25[0-5])|(2[0-4][0-9])|(1[0-9][0-9])|([1-9][0-9])|[0-9]))\/(?P<VALUE2>(3[0-2])|(2[0-9])|(1[0-9])|([0-9]))$/',
|
|
'sql' => "& (0xffffffff<<(32-{VALUE2}) & 0xffffffff) <> inet_aton('{VALUE1}')",
|
|
'function' => 'inet_aton'
|
|
),
|
|
self::OPER_IS_EMPTY => array
|
|
(
|
|
'name' => 'is empty',
|
|
'sql' => 'LIKE ""',
|
|
'null' => TRUE
|
|
),
|
|
self::OPER_IS_NOT_EMPTY => array
|
|
(
|
|
'name' => 'is not empty',
|
|
'sql' => 'NOT LIKE ""',
|
|
'null' => TRUE
|
|
)
|
|
);
|
|
|
|
/**
|
|
* Array with definition of types and its operations
|
|
* @var array
|
|
*/
|
|
protected $operation_types = array
|
|
(
|
|
'combo' => array
|
|
(
|
|
self::OPER_IS,
|
|
self::OPER_IS_NOT,
|
|
self::OPER_CONTAINS,
|
|
self::OPER_CONTAINS_NOT
|
|
),
|
|
'select' => array
|
|
(
|
|
self::OPER_IS,
|
|
self::OPER_IS_NOT
|
|
),
|
|
'text' => array
|
|
(
|
|
self::OPER_CONTAINS,
|
|
self::OPER_CONTAINS_NOT,
|
|
self::OPER_IS,
|
|
self::OPER_IS_NOT,
|
|
self::OPER_IS_EMPTY,
|
|
self::OPER_IS_NOT_EMPTY
|
|
),
|
|
'number' => array
|
|
(
|
|
self::OPER_EQUAL,
|
|
self::OPER_EQUAL_NOT,
|
|
self::OPER_SMALLER,
|
|
self::OPER_SMALLER_OR_EQUAL,
|
|
self::OPER_GREATER,
|
|
self::OPER_GREATER_OR_EQUAL
|
|
),
|
|
'bit' => array
|
|
(
|
|
self::OPER_BIT_IS,
|
|
self::OPER_BIT_IS_NOT
|
|
),
|
|
'date' => array
|
|
(
|
|
self::OPER_EQUAL,
|
|
self::OPER_EQUAL_NOT,
|
|
self::OPER_SMALLER,
|
|
self::OPER_SMALLER_OR_EQUAL,
|
|
self::OPER_GREATER,
|
|
self::OPER_GREATER_OR_EQUAL
|
|
),
|
|
'select_number' => array
|
|
(
|
|
self::OPER_IS,
|
|
self::OPER_IS_NOT,
|
|
self::OPER_EQUAL,
|
|
self::OPER_EQUAL_NOT,
|
|
self::OPER_SMALLER,
|
|
self::OPER_SMALLER_OR_EQUAL,
|
|
self::OPER_GREATER,
|
|
self::OPER_GREATER_OR_EQUAL
|
|
),
|
|
'network_address' => array
|
|
(
|
|
self::OPER_IS,
|
|
self::OPER_IS_NOT,
|
|
self::OPER_CONTAINS,
|
|
self::OPER_CONTAINS_NOT,
|
|
self::OPER_NETWORK_IS_IN,
|
|
self::OPER_NETWORK_IS_NOT_IN
|
|
)
|
|
);
|
|
|
|
/**
|
|
* Array with definition of minlengths of types
|
|
* @var array
|
|
*/
|
|
protected $minlengths = array
|
|
(
|
|
'combo' => 0,
|
|
'select' => 0,
|
|
'text' => 1,
|
|
'bit' => 0,
|
|
'date' => 1,
|
|
'select_number' => 0,
|
|
'network_address' => 1
|
|
);
|
|
|
|
/**
|
|
* Array with definition of return type of type (key or value)
|
|
* @var array
|
|
*/
|
|
protected $returns = array
|
|
(
|
|
'combo' => 'value',
|
|
'select' => 'key',
|
|
'text' => 'value',
|
|
'bit' => 'key',
|
|
'number' => 'value',
|
|
'date' => 'value',
|
|
'select_number' => 'key',
|
|
'network_address' => 'value'
|
|
);
|
|
|
|
/**
|
|
* Constructor, sets table name and compiles values from $_GET
|
|
*
|
|
* @author Michal Kliment
|
|
* @param string $table
|
|
*/
|
|
public function __construct($table = '')
|
|
{
|
|
$this->table = $table;
|
|
|
|
$this->template = new View ($this->template);
|
|
|
|
$this->types = array();
|
|
$this->operations = array();
|
|
$this->values = array();
|
|
|
|
$types = Input::instance()->get('types');
|
|
$operations = Input::instance()->get('opers');
|
|
$values = Input::instance()->get('values');
|
|
$tables = Input::instance()->get('tables');
|
|
$default = Input::instance()->get('default');
|
|
|
|
if (count($values))
|
|
{
|
|
foreach ($values as $i => $value)
|
|
{
|
|
$value = trim($value);
|
|
|
|
if ($value != '' || (
|
|
isset($this->opers[$operations[$i]]['null']) &&
|
|
$this->opers[$operations[$i]]['null']
|
|
))
|
|
{
|
|
$this->values[] = $value;
|
|
$this->types[] = $types[$i];
|
|
$this->operations[] = $operations[$i];
|
|
$this->tables[] = $tables[$i];
|
|
$this->default[] = $default[$i];
|
|
$this->default_count += $default[$i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Automatic loads filters from $_GET
|
|
*
|
|
* @author Michal Kliment
|
|
* @return int
|
|
*/
|
|
public function autoload()
|
|
{
|
|
$loaded = 0;
|
|
foreach ($this->types as $i => $type)
|
|
{
|
|
$loaded++;
|
|
|
|
$filter = new Filter($type, $this->tables[$i]);
|
|
|
|
$this->filters[$type] = $filter;
|
|
}
|
|
return $loaded;
|
|
}
|
|
|
|
/**
|
|
* Adds new filter to filter form
|
|
*
|
|
* @author Michal Kliment
|
|
* @param string $name
|
|
* @return Filter object
|
|
*/
|
|
public function add($name)
|
|
{
|
|
$filter = new Filter($name, $this->table);
|
|
|
|
$this->filters[$name] = $filter;
|
|
|
|
return $filter;
|
|
}
|
|
|
|
/**
|
|
* Loads default filter's values
|
|
*
|
|
* @author Michal Kliment
|
|
* @return int
|
|
*/
|
|
private function load_default()
|
|
{
|
|
if (!count ($this->values))
|
|
{
|
|
foreach ($this->filters as $filter)
|
|
{
|
|
foreach ($filter->default as $default)
|
|
{
|
|
$this->values[] = $default['value'];
|
|
$this->types[] = $filter->name;
|
|
$this->operations[] = $default['oper'];
|
|
$this->default[] = 1;
|
|
$this->default_count++;
|
|
}
|
|
}
|
|
}
|
|
return $this->default_count;
|
|
}
|
|
|
|
/**
|
|
* Renders filter form as HTML
|
|
*
|
|
* @author Michal Kliment
|
|
* @return string
|
|
*/
|
|
public function html()
|
|
{
|
|
// load default filter's values
|
|
$this->load_default();
|
|
|
|
// local variables
|
|
$types = array();
|
|
$value_options = array();
|
|
$js_operation_values = array();
|
|
$js_types = array();
|
|
$callbacks = array();
|
|
$minlengths = array();
|
|
$withouts = array();
|
|
$tables = array();
|
|
$classes = array();
|
|
|
|
foreach ($this->filters as $filter)
|
|
{
|
|
$types[$filter->name] = $filter->label;
|
|
|
|
foreach ($this->operation_types[$filter->type] as $operation_type)
|
|
{
|
|
$js_operation_values[$filter->name][$operation_type] = _($this->opers[$operation_type]['name']);
|
|
}
|
|
|
|
$js_types[$filter->name] = $filter->type;
|
|
$value_options[$filter->name] = $filter->values;
|
|
|
|
if ($filter->callback != '')
|
|
$callbacks[$filter->name] = url_lang::base().$filter->callback;
|
|
|
|
if (isset($this->minlengths[$filter->type]))
|
|
{
|
|
$minlengths[$filter->name] = $this->minlengths[$filter->type];
|
|
$withouts[$filter->name] = ($this->minlengths[$filter->type]) ? 1 : 0;
|
|
}
|
|
else
|
|
$withouts[$filter->name] = 1;
|
|
|
|
$tables[$filter->name] = $filter->table;
|
|
|
|
if (is_array($filter->class))
|
|
$classes[$filter->name] = $filter->class;
|
|
else
|
|
$classes[$filter->name] = array('all' => $filter->class);
|
|
}
|
|
|
|
$operations = array();
|
|
foreach ($this->opers as $i => $operation)
|
|
{
|
|
$operations[$i] = url_lang::lang('texts.'.$operation['name']);
|
|
}
|
|
|
|
$this->template->type_values = $types;
|
|
$this->template->operation_values = $operations;
|
|
$this->template->js_operation_values = $js_operation_values;
|
|
$this->template->js_types = $js_types;
|
|
$this->template->value_options = $value_options;
|
|
$this->template->callbacks = $callbacks;
|
|
$this->template->minlengths = $minlengths;
|
|
$this->template->withouts = $withouts;
|
|
$this->template->tables = $tables;
|
|
$this->template->classes = $classes;
|
|
|
|
$this->template->default = $this->default;
|
|
$this->template->default_count = $this->default_count;
|
|
$this->template->types = $this->types;
|
|
$this->template->operations = $this->operations;
|
|
$this->template->values = $this->values;
|
|
return $this->template->render();
|
|
}
|
|
|
|
/**
|
|
* Returns SQL query (only part after WHERE) to use in model methods
|
|
*
|
|
* @author Michal Kliment
|
|
* @return string
|
|
*/
|
|
public function as_sql ()
|
|
{
|
|
// loads default filter's values
|
|
$this->load_default();
|
|
|
|
$queries = array();
|
|
|
|
foreach ($this->types as $i => $type)
|
|
{
|
|
$filter = $this->filters[$type];
|
|
|
|
$value = trim($this->values[$i]);
|
|
|
|
if ($this->returns[$filter->type] == 'key' &&
|
|
arr::search($value, $filter->values) !== FALSE)
|
|
{
|
|
$value = arr::search($value, $filter->values);
|
|
}
|
|
|
|
$sql = $this->opers[$this->operations[$i]]['sql'];
|
|
|
|
if (isset($this->opers[$this->operations[$i]]['pattern']))
|
|
{
|
|
if (!preg_match(
|
|
$this->opers[$this->operations[$i]]['pattern'],
|
|
mysql_real_escape_string($value), $matches
|
|
))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foreach ($matches as $key => $value)
|
|
{
|
|
$sql = str_replace('{'.$key.'}', mysql_real_escape_string($value), $sql);
|
|
}
|
|
}
|
|
|
|
$table_pom = mb_strlen($filter->table) ? $filter->table . '.' : '';
|
|
|
|
if (isset($this->opers[$this->operations[$i]]['function']))
|
|
{
|
|
$queries[] = $this->opers[$this->operations[$i]]['function']
|
|
. "(" . $table_pom . $filter->name . ") "
|
|
. str_replace("{VALUE}", mysql_real_escape_string($value), $sql);
|
|
}
|
|
else
|
|
{
|
|
$queries[] = $table_pom . $filter->name . " "
|
|
. str_replace("{VALUE}", mysql_real_escape_string($value), $sql);
|
|
}
|
|
}
|
|
|
|
return implode (" AND ", $queries);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return array
|
|
*/
|
|
public function as_array()
|
|
{
|
|
// loads default filter's values
|
|
$this->load_default();
|
|
|
|
$data = array();
|
|
foreach ($this->types as $i => $type)
|
|
{
|
|
$filter = $this->filters[$type];
|
|
|
|
$value = trim($this->values[$i]);
|
|
|
|
if ($this->returns[$filter->type] == 'key' &&
|
|
arr::search($value, $filter->values) !== FALSE)
|
|
{
|
|
$value = arr::search($value, $filter->values);
|
|
}
|
|
|
|
$data[] = array
|
|
(
|
|
'key' => $filter->name,
|
|
'value' => $value,
|
|
'op' => $this->operations[$i]
|
|
);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Prints filter form as HTML
|
|
*
|
|
* @author Michal Kliment
|
|
* @return string
|
|
*/
|
|
public function __toString()
|
|
{
|
|
return $this->html();
|
|
}
|
|
}
|