Revize 2339
Přidáno uživatelem Ondřej Fibich před asi 10 roky(ů)
freenetis/branches/modularity/application/libraries/Filter_form.php | ||
---|---|---|
<?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;
|
||
|
||
/**
|
||
*Array with states (on/off) of filters
|
||
* @var array
|
||
*/
|
||
protected $states = array();
|
||
|
||
/**
|
||
* Default query for filter form
|
||
* @var integer
|
||
*/
|
||
protected $default_query_id = NULL;
|
||
|
||
/**
|
||
* Base URL of filter form
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $base_url = NULL;
|
||
|
||
/**
|
||
* State of possibility of add new query
|
||
*
|
||
* @var boolean
|
||
*/
|
||
protected $can_add = FALSE;
|
||
|
||
/**
|
||
* Indicates whether the filter form configuration was loaded from database.
|
||
*
|
||
* @var boolean
|
||
*/
|
||
protected $loaded_from_saved_query = FALSE;
|
||
|
||
/**
|
||
* Indicates whether the filter form configuration that was loaded from
|
||
* database is default.
|
||
*
|
||
* @var boolean
|
||
*/
|
||
protected $loaded_from_default_saved_query = FALSE;
|
||
|
||
/**
|
||
* 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'
|
||
);
|
||
|
||
/**
|
||
* Boolean value whether it is first load of filters (#442)
|
||
* @var boolean
|
||
*/
|
||
protected $first_load = FALSE;
|
||
|
||
/**
|
||
* Constructor, sets table name and compiles values from $_GET
|
||
*
|
||
* @author Michal Kliment
|
||
* @param string $table
|
||
*/
|
||
public function __construct($table = '', $base_url = '')
|
||
{
|
||
$this->table = $table;
|
||
|
||
$this->base_url = ($base_url != '') ? $base_url : url_lang::current(2);
|
||
|
||
$this->template = new View ($this->template);
|
||
|
||
$this->types = array();
|
||
$this->operations = array();
|
||
$this->values = array();
|
||
|
||
// create query model
|
||
$this->query_model = new Filter_query_Model();
|
||
|
||
// loads all queries belongs to current url
|
||
$this->queries = $this->query_model->get_all_queries_by_url($this->base_url);
|
||
foreach ($this->queries as $query)
|
||
{
|
||
// find default query
|
||
if ($query->default)
|
||
$this->default_query_id = $query->id;
|
||
}
|
||
|
||
$query = Input::instance()->get('query');
|
||
|
||
// load query from database (because of #895 can be from different URL)
|
||
if ($query && is_numeric($query))
|
||
{
|
||
$loaded_query = new Filter_query_Model($query);
|
||
|
||
if ($loaded_query && $loaded_query->id) {
|
||
|
||
$data = json_decode($loaded_query->values, TRUE);
|
||
|
||
$on = @$data["on"];
|
||
$types = @$data["types"];
|
||
$operations = @$data["opers"];
|
||
$values = @$data["values"];
|
||
$tables = @$data["tables"];
|
||
|
||
$this->loaded_from_saved_query = TRUE;
|
||
|
||
}
|
||
else
|
||
{
|
||
$on = $types = $operations = $values = $tables = NULL;
|
||
status::warning('Invalid saved query');
|
||
}
|
||
|
||
$this->first_load = FALSE;
|
||
}
|
||
// load query from URL
|
||
else
|
||
{
|
||
$on = Input::instance()->get('on');
|
||
$types = Input::instance()->get('types');
|
||
$operations = Input::instance()->get('opers');
|
||
$values = Input::instance()->get('values');
|
||
$tables = Input::instance()->get('tables');
|
||
|
||
$this->can_add = TRUE;
|
||
$this->loaded_from_saved_query = FALSE;
|
||
|
||
$this->first_load = FALSE;
|
||
}
|
||
|
||
$this->keys = Input::instance()->get('keys');
|
||
$this->vals = Input::instance()->get('vals');
|
||
|
||
// query is empty, use default from database
|
||
if (!$on && !$types && !$operations && !$values && !$tables && $this->default_query_id)
|
||
{
|
||
$data = json_decode($this->queries[$this->default_query_id]->values, TRUE);
|
||
|
||
$on = @$data["on"];
|
||
$types = @$data["types"];
|
||
$operations = @$data["opers"];
|
||
$values = @$data["values"];
|
||
$tables = @$data["tables"];
|
||
|
||
$this->can_add = FALSE;
|
||
$this->loaded_from_saved_query = TRUE;
|
||
$this->loaded_from_default_saved_query = TRUE;
|
||
|
||
$this->first_load = TRUE;
|
||
}
|
||
|
||
// load data
|
||
if (count($values))
|
||
{
|
||
$this->tables = $tables;
|
||
|
||
$offset = 0;
|
||
for ($i=0;$i<=max(array_keys($values));$i++)
|
||
{
|
||
if (isset($on[$i]) && is_array($values[$i]))
|
||
{
|
||
$this->states[$i-$offset] = $on[$i];
|
||
$this->values[$i-$offset] = array_map("trim", $values[$i]);
|
||
$this->types[$i-$offset] = $types[$i];
|
||
$this->operations[$i-$offset] = $operations[$i];
|
||
}
|
||
else
|
||
$offset++;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
$this->can_add = FALSE;
|
||
|
||
$this->first_load = TRUE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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, isset($this->tables[$type]) ? $this->tables[$type] : '');
|
||
|
||
if (isset($this->keys[$filter->name]))
|
||
{
|
||
$this->values[$i] = $this->keys[$filter->name][array_search($this->values[$i], $this->vals[$filter->name])];
|
||
}
|
||
|
||
$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, $table = NULL)
|
||
{
|
||
if (!$table)
|
||
{
|
||
$table = $this->table;
|
||
}
|
||
else
|
||
{
|
||
$name .= '/'.$table;
|
||
}
|
||
|
||
$filter = new Filter($name, $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->states[] = TRUE;
|
||
$this->values[] = (is_array($default['value'])) ? $default['value'] : array($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();
|
||
|
||
$types = $this->types;
|
||
$type_options = array();
|
||
$states = $this->states;
|
||
$operations = $this->operations;
|
||
$operation_options = array();
|
||
$values = $this->values;
|
||
$tables = $this->tables;
|
||
$default = $this->default;
|
||
$keys = array();
|
||
|
||
$js_data = array();
|
||
|
||
// iterate all filters
|
||
foreach ($this->filters as $filter)
|
||
{
|
||
$type_options[$filter->name] = $filter->label;
|
||
|
||
$tables[$filter->name] = $filter->table;
|
||
|
||
// save data for javascript
|
||
|
||
$js_data[$filter->name]["returns"] = $this->returns[$filter->type];
|
||
|
||
if ($filter->values)
|
||
{
|
||
foreach ($filter->values as $key => $value)
|
||
$js_data[$filter->name]["values"][$key] = $value;
|
||
}
|
||
else
|
||
$js_data[$filter->name]["values"] = '';
|
||
|
||
foreach ($this->operation_types[$filter->type] as $operation_type)
|
||
$js_data[$filter->name]["operations"][$operation_type] = __($this->opers[$operation_type]['name']);
|
||
|
||
$js_data[$filter->name]["callback"] = $filter->callback;
|
||
|
||
$js_data[$filter->name]["classes"] = (is_array($filter->class)) ? $filter->class : array('all' => $filter->class);
|
||
|
||
$js_data[$filter->name]["css_classes"] = $filter->css_class;
|
||
}
|
||
|
||
foreach ($this->opers as $i => $operation)
|
||
$operation_options[$i] = __($operation['name']);
|
||
|
||
// add one extra empty filter
|
||
$types[] = NULL;
|
||
$states[] = 0;
|
||
$operations[] = NULL;
|
||
$values[] = NULL;
|
||
$default[] = NULL;
|
||
|
||
$this->template->base_url = $this->base_url;
|
||
$this->template->types = $types;
|
||
$this->template->type_options = $type_options;
|
||
$this->template->states = $states;
|
||
$this->template->operations = $operations;
|
||
$this->template->operation_options = $operation_options;
|
||
$this->template->values = $values;
|
||
$this->template->tables = $tables;
|
||
$this->template->default = $default;
|
||
$this->template->keys = $keys;
|
||
$this->template->classes = $filter->css_class;
|
||
|
||
$this->template->js_data = $js_data;
|
||
|
||
$this->template->queries = $this->queries;
|
||
|
||
$this->template->can_add = $this->can_add;
|
||
|
||
return $this->template->render();
|
||
}
|
||
|
||
/**
|
||
* Returns SQL query (only part after WHERE) to use in model methods
|
||
*
|
||
* @param mixed $approved_keys Array which defined columns which should be used in query.
|
||
* @author Michal Kliment
|
||
* @return string
|
||
*/
|
||
public function as_sql ($approved_keys = FALSE)
|
||
{
|
||
// loads default filter's values
|
||
$this->load_default();
|
||
|
||
$offset = 0;
|
||
|
||
$queries = array();
|
||
|
||
foreach ($this->types as $i => $type)
|
||
{
|
||
if (is_array($approved_keys) && !in_array($type, $approved_keys))
|
||
{ // not allowed => continue
|
||
continue;
|
||
}
|
||
|
||
if (!array_key_exists($type, $this->filters))
|
||
{
|
||
throw new InvalidArgumentException('Invalid option: ' . $type);
|
||
}
|
||
|
||
$filter = $this->filters[$type];
|
||
|
||
$sub_queries = array();
|
||
|
||
$values = array();
|
||
if ($this->returns[$filter->type] == 'key')
|
||
{
|
||
foreach ($this->values[$i] as $value)
|
||
{
|
||
$values[] = $value;
|
||
|
||
if (isset($filter->values[$value]))
|
||
$values[] = $filter->values[$value];
|
||
}
|
||
}
|
||
else
|
||
$values = $this->values[$i];
|
||
|
||
$notquery = false;
|
||
|
||
foreach ($values as $value)
|
||
{
|
||
if (!isset($this->opers[$this->operations[$i]]))
|
||
continue;
|
||
|
||
$sql = $this->opers[$this->operations[$i]]['sql'];
|
||
|
||
if (strpos($this->opers[$this->operations[$i]]['name'], 'not'))
|
||
$notquery = true;
|
||
|
||
if (isset($this->opers[$this->operations[$i]]['pattern']))
|
||
{
|
||
if (!preg_match(
|
||
$this->opers[$this->operations[$i]]['pattern'],
|
||
Database::instance()->escape_str($value), $matches
|
||
))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
foreach ($matches as $key => $value)
|
||
$sql = str_replace('{'.$key.'}', Database::instance()->escape_str($value), $sql);
|
||
}
|
||
|
||
$table_pom = mb_strlen($filter->table) ? $filter->table . '.' : '';
|
||
$name_pom = (strpos($filter->name, '/') == FALSE ? $filter->name : substr($filter->name, 0, strpos($filter->name, '/')));
|
||
|
||
$column = Database::instance()->escape_column(Database::instance()->escape_str($table_pom . $name_pom));
|
||
|
||
if (isset($this->opers[$this->operations[$i]]['function']))
|
||
$query = $this->opers[$this->operations[$i]]['function']. "($column)";
|
||
else
|
||
$query = $column;
|
||
|
||
$query .= " ". str_replace("{VALUE}", Database::instance()->escape_str($value), $sql);
|
||
|
||
$sub_queries[] = $query;
|
||
}
|
||
|
||
if ($notquery)
|
||
$operator = 'AND';
|
||
else
|
||
$operator = 'OR';
|
||
|
||
$queries[] = "(".implode(" $operator ", $sub_queries).")";
|
||
}
|
||
|
||
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 = array_map('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;
|
||
}
|
||
|
||
/**
|
||
* Indicates whether the filter form configuration was loaded from database.
|
||
*
|
||
* @return boolean
|
||
*/
|
||
public function is_loaded_from_saved_query()
|
||
{
|
||
return $this->loaded_from_saved_query;
|
||
}
|
||
|
||
/**
|
||
* Indicates whether the filter form configuration that was loaded from
|
||
* database is default.
|
||
*
|
||
* @return boolean
|
||
*/
|
||
public function is_loaded_from_default_saved_query()
|
||
{
|
||
return $this->loaded_from_default_saved_query;
|
||
}
|
||
|
||
/**
|
||
* Indicates whether it is first load
|
||
*
|
||
* @return boolean
|
||
*/
|
||
public function is_first_load()
|
||
{
|
||
return $this->first_load;
|
||
}
|
||
|
||
/**
|
||
* Returns base URL of the filter form.
|
||
*
|
||
* @return string URL
|
||
*/
|
||
public function get_base_url()
|
||
{
|
||
return $this->base_url;
|
||
}
|
||
|
||
/**
|
||
* Prints filter form as HTML
|
||
*
|
||
* @author Michal Kliment
|
||
* @return string
|
||
*/
|
||
public function __toString()
|
||
{
|
||
return $this->html();
|
||
}
|
||
}
|
freenetis/branches/modularity/application/libraries/MY_Controller.php | ||
---|---|---|
<?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/
|
||
*
|
||
*/
|
||
|
||
// numbers of errors
|
||
define('ACCESS', 1);
|
||
define('EMAIL', 2);
|
||
define('DATABASE', 3);
|
||
define('DATABASE_DOWNGRATE', 9);
|
||
define('DATABASE_OLD_MECHANISM', 10);
|
||
define('DATABASE_UPGRADE_NOT_ENABLED', 11);
|
||
define('RECORD', 4);
|
||
define('PAGE', 5);
|
||
define('WRITABLE', 7);
|
||
define('READONLY', 8);
|
||
|
||
// numbers of warnings, their identifier numbers have to differ from error messages
|
||
// for example when programmer misleads error and warning
|
||
define('PARAMETER', 1001);
|
||
|
||
/**
|
||
* Main controller creates menu, handles changes in svn repository (database upgrade), ...
|
||
*
|
||
* BE CAREFUL HERE, CATCH EVERY EXCEPTION, OTHERWISE FREENETIS
|
||
* WITH JUST SMALL ERROR BECOMES COMPLETELY UNUSABLE
|
||
*/
|
||
class Controller extends Controller_Core
|
||
{
|
||
/** @var integer */
|
||
const ICON_ERROR = 1;
|
||
/** @var integer */
|
||
const ICON_GOOD = 2;
|
||
/** @var integer */
|
||
const ICON_HELP = 3;
|
||
/** @var integer */
|
||
const ICON_INFO = 4;
|
||
/** @var integer */
|
||
const ICON_WARNING = 5;
|
||
|
||
/**
|
||
* Controller singleton
|
||
*
|
||
* @var Controller
|
||
*/
|
||
private static $instance;
|
||
|
||
/**
|
||
* Paths for which login is not required
|
||
*
|
||
* @var array
|
||
*/
|
||
private static $login_not_required = array
|
||
(
|
||
/* login, scheduler, instalation */
|
||
'login',
|
||
'forgotten_password',
|
||
'scheduler/run',
|
||
'installation',
|
||
'setup_config',
|
||
'setup_config/htaccess',
|
||
'setup_config/setup',
|
||
'redirect/logo',
|
||
/* registration */
|
||
'registration',
|
||
'registration/complete',
|
||
'js/registration',
|
||
'json/get_streets_by_town',
|
||
'json/get_address',
|
||
'address_points/get_gps_by_address',
|
||
'address_points/get_gps_by_address_string',
|
||
);
|
||
|
||
/** @var unknown_type */
|
||
public $arr;
|
||
/** @var Setting_Model Settings */
|
||
public $settings = NULL;
|
||
/** @var integer */
|
||
public $popup = 0;
|
||
/** @var integer */
|
||
public $dialog = 0;
|
||
/** @var boolean */
|
||
public $noredirect = FALSE;
|
||
/** @var boolean */
|
||
public $user_has_voip = 0;
|
||
/** @var string */
|
||
public $ip_address_span = '';
|
||
/** @var integer */
|
||
public $unread_user_mails = 0;
|
||
/** @var integer */
|
||
public $count_of_unclosed_logged_errors = 0;
|
||
/** @var integer */
|
||
public $devices_down_count = 0;
|
||
/** @var Database_Result */
|
||
public $user_favourites_pages = NULL;
|
||
/** @var boolean $axo_doc_access Enable access to AXO doc */
|
||
public $axo_doc_access = FALSE;
|
||
/** @var integer $member_id ID of logged member */
|
||
protected $member_id;
|
||
/** @var integer $user_id ID of logged user */
|
||
protected $user_id;
|
||
/** @var integer $account_id ID of logged member account */
|
||
protected $member_account_id = 1;
|
||
/** @var Session */
|
||
protected $session;
|
||
/** @var $groups_aro_map Groups_aro_map_Model */
|
||
private $groups_aro_map;
|
||
|
||
/**
|
||
* Contruct of controller, creates singleton or return it
|
||
*/
|
||
public function __construct()
|
||
{
|
||
parent::__construct();
|
||
|
||
// This part only needs to be run once
|
||
if (self::$instance === NULL)
|
||
{
|
||
// init sessions
|
||
$this->session = Session::instance();
|
||
|
||
// store user ID from session
|
||
$this->user_id = $this->session->get('user_id', 0);
|
||
|
||
// store member ID from session
|
||
$this->member_id = $this->session->get('member_id', 0);
|
||
|
||
// test if visitor is logged in, or he accesses public
|
||
// controllers like registration, redirect, installation, etc.
|
||
if (!in_array(url_lang::current(), self::$login_not_required) &&
|
||
url_lang::current(1) != 'web_interface' &&
|
||
url_lang::current(2) != 'devices/export' &&
|
||
!$this->user_id)
|
||
{
|
||
// Not logged in - redirect to login page
|
||
$this->session->set_flash('err_message', __('Must be logged in'));
|
||
|
||
// Do not logout after login
|
||
if (url_lang::current(1) != 'login' &&
|
||
url_lang::current(1) != 'js')
|
||
{
|
||
$this->session->set('referer', url_lang::current());
|
||
}
|
||
else
|
||
{
|
||
$this->session->set('referer', '');
|
||
}
|
||
|
||
// Redirect to login
|
||
url::redirect('login');
|
||
|
||
// Die
|
||
die();
|
||
}
|
||
|
||
// init settings
|
||
$this->settings = new Settings();
|
||
|
||
// if true, freenetis will run in popup mode (without header and menu)
|
||
$this->popup = (isset($_GET['popup']) && $_GET['popup']) ? 1 : 0;
|
||
|
||
// if true, freenetis will run in text mod for dialog
|
||
$this->dialog = (isset($_GET['dialog']) && $_GET['dialog']) ? 1 : 0;
|
||
|
||
// if true, method redirect will not redirect
|
||
$this->noredirect = ($this->input->get('noredirect') || $this->input->post('noredirect'));
|
||
|
||
// config file doesn't exist, we must create it
|
||
if (!file_exists('config.php') || !file_exists('.htaccess'))
|
||
{
|
||
// protection before loop
|
||
if (url_lang::current(1) == 'setup_config')
|
||
return;
|
||
|
||
if (!file_exists('.htaccess'))
|
||
{
|
||
Settings::set('index_page', 1);
|
||
}
|
||
|
||
url::redirect('setup_config');
|
||
}
|
||
|
||
// protection before loop
|
||
if (url_lang::current(1) == 'installation')
|
||
{
|
||
return;
|
||
}
|
||
|
||
// test database connection
|
||
if (!db::test())
|
||
{
|
||
Controller::error(DATABASE);
|
||
}
|
||
|
||
// db schema version is null => we must run install
|
||
if (!Version::get_db_version())
|
||
{
|
||
url::redirect('installation');
|
||
}
|
||
// db schema is not up to date => we must run upgrade
|
||
else if (!Version::is_db_up_to_date())
|
||
{
|
||
// change database encoding if incorect
|
||
try
|
||
{
|
||
$db = Database::instance();
|
||
|
||
/**
|
||
* @todo in the future the collate should be used according
|
||
* to language system settings
|
||
*/
|
||
if ($db->get_variable_value('character_set_database') != 'utf8' ||
|
||
$db->get_variable_value('collation_database') != 'utf8_czech_ci')
|
||
{
|
||
$db->alter_db_character_set(
|
||
Config::get('db_name'), 'utf8', 'utf8_czech_ci'
|
||
);
|
||
}
|
||
}
|
||
catch (Exception $e)
|
||
{
|
||
Log::add_exception($e);
|
||
$m = __('Cannot set database character set to UTF8');
|
||
self::showbox($m, self::ICON_ERROR);
|
||
}
|
||
|
||
// try to open mutex file
|
||
if (($f = @fopen(server::base_dir().'/upload/mutex', 'w')) === FALSE)
|
||
{
|
||
// directory is not writeable
|
||
self::error(WRITABLE, server::base_dir().'/upload/');
|
||
}
|
||
|
||
// acquire an exclusive access to file
|
||
// wait while database is being updated
|
||
if (flock($f, LOCK_EX))
|
||
{
|
||
// first access - update db
|
||
// other access - skip
|
||
if (!Version::is_db_up_to_date())
|
||
{
|
||
try
|
||
{
|
||
Version::make_db_up_to_date();
|
||
}
|
||
catch (Not_Enabled_Upgrade_Exception $neu)
|
||
{
|
||
self::error(DATABASE_UPGRADE_NOT_ENABLED, $neu->getMessage());
|
||
}
|
||
catch (Old_Mechanism_Exception $ome)
|
||
{
|
||
self::error(DATABASE_OLD_MECHANISM);
|
||
}
|
||
catch (Database_Downgrate_Exception $dde)
|
||
{
|
||
self::error(DATABASE_DOWNGRATE);
|
||
}
|
||
catch (Exception $e)
|
||
{
|
||
throw new Exception(
|
||
__('Database upgrade failed') . ': ' .
|
||
$e->getMessage(), 0, $e
|
||
);
|
||
}
|
||
}
|
||
|
||
// unlock mutex file
|
||
flock($f, LOCK_UN);
|
||
}
|
||
|
||
// close mutex file
|
||
fclose($f);
|
||
}
|
||
|
||
// load these variables only if preprocessor is enabled and user is logged
|
||
if ($this->is_preprocesor_enabled() && $this->user_id)
|
||
{
|
||
// for preprocessing some variable
|
||
try
|
||
{
|
||
$this->preprocessor();
|
||
}
|
||
catch(Exception $e)
|
||
{
|
||
Log::add_exception($e);
|
||
}
|
||
}
|
||
|
||
// Singleton instance
|
||
self::$instance = $this;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Singleton instance of Controller.
|
||
*
|
||
* @author Michal Kliment
|
||
* @return Controller object
|
||
*/
|
||
public static function & instance()
|
||
{
|
||
// Create the instance if it does not exist
|
||
empty(self::$instance) and new Controller;
|
||
|
||
return self::$instance;
|
||
}
|
||
|
||
/**
|
||
* Function shows error of given message number.
|
||
*
|
||
* @param integer $message_type
|
||
* @param string $content
|
||
*/
|
||
public static function error($message_type, $content = NULL)
|
||
{
|
||
$response_code = NULL;
|
||
$fatal = FALSE;
|
||
|
||
switch ($message_type)
|
||
{
|
||
case ACCESS:
|
||
$message = url_lang::lang('states.Access denied');
|
||
$response_code = 403; // Forbidden
|
||
break;
|
||
case EMAIL:
|
||
$message = url_lang::lang('states.Failed to send e-mail') .
|
||
'<br />' . url_lang::lang('states.Please check settings.');
|
||
$response_code = 500; // Internal server error
|
||
break;
|
||
case DATABASE:
|
||
$message = url_lang::lang('states.Failed to connect to database') .
|
||
'<br />' . url_lang::lang('states.Please check settings.');
|
||
$response_code = 500; // Internal server error
|
||
$fatal = TRUE;
|
||
break;
|
||
case DATABASE_DOWNGRATE:
|
||
$message = url_lang::lang('states.Failed to update database') .
|
||
'<br />' . url_lang::lang('states.Downgrade not allowed.');
|
||
$response_code = 500; // Internal server error
|
||
$fatal = TRUE;
|
||
break;
|
||
case DATABASE_OLD_MECHANISM:
|
||
$message = url_lang::lang('states.Failed to update database') .
|
||
'<br /><br /><span style="font-size:12px">' .
|
||
url_lang::lang('help.old_upgrade_system') . '</span>';
|
||
$response_code = 500; // Internal server error
|
||
$fatal = TRUE;
|
||
break;
|
||
case DATABASE_UPGRADE_NOT_ENABLED:
|
||
$message = url_lang::lang('states.Failed to update database');
|
||
$response_code = 500; // Internal server error
|
||
$fatal = TRUE;
|
||
break;
|
||
case RECORD:
|
||
$message = url_lang::lang('states.This record does not exist');
|
||
$response_code = 404; // Not found
|
||
break;
|
||
case PAGE:
|
||
$message = url_lang::lang('states.Page not found');
|
||
$response_code = 404; // Not found
|
||
break;
|
||
case WRITABLE:
|
||
$message = url_lang::lang('states.Directory or file is not writable.');
|
||
$response_code = 500; // Internal server error
|
||
break;
|
||
case READONLY:
|
||
$message = url_lang::lang('states.Item is read only.');
|
||
$response_code = 403; // Internal server error
|
||
break;
|
||
default:
|
||
$message = url_lang::lang('states.Unknown error message');
|
||
$response_code = 500; // Internal server error
|
||
break;
|
||
}
|
||
|
||
self::showbox($message, self::ICON_ERROR, $content, $response_code, $fatal);
|
||
}
|
||
|
||
/**
|
||
* Function shows warning of given message number.
|
||
*
|
||
* @param integer $message_type
|
||
* @param string $content
|
||
*/
|
||
public static function warning($message_type, $content = NULL)
|
||
{
|
||
$response_code = NULL;
|
||
|
||
switch ($message_type)
|
||
{
|
||
case PARAMETER:
|
||
$message = url_lang::lang('states.Parameter required');
|
||
$response_code = 404; // Internal server error
|
||
break;
|
||
default:
|
||
$message = url_lang::lang('states.Unknown warning message');
|
||
$response_code = 500; // Internal server error
|
||
break;
|
||
}
|
||
|
||
self::showbox($message, self::ICON_WARNING, $content, $response_code);
|
||
}
|
||
|
||
/**
|
||
* Function renders error and warning messages.
|
||
*
|
||
* @param string $message Message to display
|
||
* @param integer $type Type of message (error, info, warning, etc.)
|
||
* @param string $content Some message that describe message in more detail way
|
||
* @param string $http_response_code Send some response code (xxx)
|
||
* @param boolean $fatal_error Is this error a fatal error?
|
||
*/
|
||
private static function showbox($message, $type, $content = NULL,
|
||
$http_response_code = NULL, $fatal_error = FALSE)
|
||
{
|
||
if ($fatal_error)
|
||
{
|
||
$view = new View('main_statesbox');
|
||
}
|
||
else
|
||
{
|
||
$view = new View('main');
|
||
}
|
||
|
||
$view->content = new View('statesbox');
|
||
|
||
$src = NULL;
|
||
|
||
switch ($type)
|
||
{
|
||
case self::ICON_ERROR:
|
||
$view->title = __('Error');
|
||
$src = 'media/images/states/error.png';
|
||
break;
|
||
case self::ICON_GOOD:
|
||
$view->title = __('Good');
|
||
$src = 'media/images/states/good.png';
|
||
break;
|
||
case self::ICON_HELP:
|
||
$view->title = __('Help');
|
||
$src = 'media/images/states/help.png';
|
||
break;
|
||
case self::ICON_INFO:
|
||
$view->title = __('Info');
|
||
$src = 'media/images/states/info.png';
|
||
break;
|
||
case self::ICON_WARNING:
|
||
$view->title = __('Warning');
|
||
$src = 'media/images/states/warning.png';
|
||
break;
|
||
}
|
||
|
||
if ($http_response_code)
|
||
{
|
||
header("HTTP/1.1 $http_response_code");
|
||
}
|
||
|
||
$view->content->icon = html::image(array
|
||
(
|
||
'src' => $src,
|
||
'width' => '100',
|
||
'height' => '100',
|
||
'alt' => 'Image',
|
||
'class' => 'noborder'
|
||
));
|
||
|
||
$view->content->message = $message;
|
||
|
||
if (isset($content))
|
||
{
|
||
$view->content->content = $content;
|
||
}
|
||
|
||
$view->loading_hide = TRUE;
|
||
$view->render(TRUE);
|
||
|
||
// must be die() - else it will be render twice !
|
||
die();
|
||
}
|
||
|
||
/**
|
||
* Checks user's access to system
|
||
*
|
||
* @author Ondřej Fibich
|
||
*
|
||
* @param type $axo_section_value AXO section value - Controller name
|
||
* @param type $axo_value AXO value - part of Controller
|
||
* @param type $aco_type ACO type of action (view, new, edit, delete, confirm)
|
||
* @param integer $member_id Member to check access
|
||
* @param boolean $force_own Force to use own rules for not logged user
|
||
* Used at: Phone_invoices_Controller#user_field()
|
||
* @return bool
|
||
*/
|
||
private function acl_check(
|
||
$axo_section, $axo_value, $aco_type, $member_id = NULL,
|
||
$force_own = FALSE)
|
||
{
|
||
// groups aro map loaded?
|
||
if (empty($this->groups_aro_map))
|
||
{
|
||
$this->groups_aro_map = new Groups_aro_map_Model();
|
||
}
|
||
|
||
// check own?
|
||
if (($member_id == $_SESSION['member_id']) || $force_own)
|
||
{
|
||
// check own access
|
||
if ($this->groups_aro_map->has_access(
|
||
$_SESSION['user_id'], $aco_type . '_own',
|
||
$axo_section, $axo_value
|
||
))
|
||
{
|
||
// access valid
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// check all
|
||
return $this->groups_aro_map->has_access(
|
||
$_SESSION['user_id'], $aco_type . '_all',
|
||
$axo_section, $axo_value
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Checks if user is in ARO group
|
||
*
|
||
* @author Ondřej Fibich
|
||
* @param integer $group_id ARO group ID
|
||
* @param integer $aro_id User ID
|
||
* @return boolean true if exists false otherwise
|
||
*/
|
||
public function is_user_in_group($aro_group_id, $aro_id)
|
||
{
|
||
return $this->groups_aro_map->groups_aro_map_exists($aro_group_id, $aro_id);
|
||
}
|
||
|
||
/**
|
||
* Fuction checks access rights
|
||
* Return true if currently logged user (stored in $_SESSION['user_id'])
|
||
* may view own $axo_value object in $axo_section
|
||
* (and in variable $member_id is his own id of member) or if currently logged user
|
||
* may view all $axo_value object in $axo_section else return false
|
||
*
|
||
* @param $axo_section Group of objects to view
|
||
* @param $axo_value Object to view
|
||
* @param $member_id Optional variable, id of other member
|
||
* who is being showed by logged member
|
||
* @param boolean $force_own Force to use own rules for not logged user
|
||
* Used at: Phone_invoices_Controller#user_field()
|
||
* @return boolean returns true if member has enough access rights
|
||
*/
|
||
public function acl_check_view(
|
||
$axo_section, $axo_value, $member_id = NULL, $force_own = FALSE)
|
||
{
|
||
return $this->acl_check(
|
||
$axo_section, $axo_value, 'view', $member_id, $force_own
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Fuction checks access rights
|
||
* Return true if currently logged user (stored in $_SESSION['user_id'])
|
||
* may view own $axo_value object in $axo_section
|
||
* (and in variable $member_id is his own id of member) or if currently logged user
|
||
* may edit all $axo_value object in $axo_section else return false
|
||
*
|
||
* @param $axo_section Group of objects to edit
|
||
* @param $axo_value Object to edit
|
||
* @param $member_id Optional variable, id of other member
|
||
* who is being showed by logged member
|
||
* @param boolean $force_own Force to use own rules for not logged user
|
||
* Used at: Phone_invoices_Controller#user_field()
|
||
* @return boolean Returns true if member has enough access rights
|
||
*/
|
||
public function acl_check_edit(
|
||
$axo_section, $axo_value, $member_id = NULL, $force_own = FALSE)
|
||
{
|
||
return $this->acl_check(
|
||
$axo_section, $axo_value, 'edit', $member_id, $force_own
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Fuction checks access rights
|
||
* Return true if currently logged user (stored in $_SESSION['user_id'])
|
||
* may view own $axo_value object in $axo_section
|
||
* (and in variable $member_id is his own id of member) or if currently logged user
|
||
* may add all $axo_value object in $axo_section else return false
|
||
*
|
||
* @param $axo_section Group of objects to edit
|
||
* @param $axo_value Object to add
|
||
* @param $member_id Optional variable, id of other member
|
||
* who is being showed by logged member
|
||
* @param boolean $force_own Force to use own rules for not logged user
|
||
* Used at: Phone_invoices_Controller#user_field()
|
||
* @return boolean Returns true if member has enough access rights
|
||
*/
|
||
public function acl_check_new(
|
||
$axo_section, $axo_value, $member_id = NULL, $force_own = FALSE)
|
||
{
|
||
return $this->acl_check(
|
||
$axo_section, $axo_value, 'new', $member_id, $force_own
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Fuction checks access rights
|
||
* Return true if currently logged user (stored in $_SESSION['user_id'])
|
||
* may view own $axo_value object in $axo_section
|
||
* (and in variable $member_id is his own id of member) or if currently logged user
|
||
* may delete all $axo_value object in $axo_section else return false
|
||
*
|
||
* @param $axo_section Group of objects to edit
|
||
* @param $axo_value Object to delete
|
||
* @param $member_id Optional variable, id of other member
|
||
* who is being showed by logged member
|
||
* @param boolean $force_own Force to use own rules for not logged user
|
||
* Used at: Phone_invoices_Controller#user_field()
|
||
* @return boolean Returns true if member has enough access rights
|
||
*/
|
||
public function acl_check_delete(
|
||
$axo_section, $axo_value, $member_id = NULL, $force_own = FALSE)
|
||
{
|
||
return $this->acl_check(
|
||
$axo_section, $axo_value, 'delete', $member_id, $force_own
|
||
);
|
||
}
|
||
|
||
/**
|
||
* This methods defines whether the preprocessor of MY_Controller is loaded
|
||
* or not. By default preprocessor is loaded, for changing of this state
|
||
* this method should be overriden in child class. (#328)
|
||
*
|
||
* @author Ondřej Fibich
|
||
* @return boolean Is preprocessor loaded?
|
||
*/
|
||
protected function is_preprocesor_enabled()
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
/**
|
||
* Function to preprocessing of some useful variables
|
||
*
|
||
* @author Michal Kliment
|
||
*/
|
||
private function preprocessor()
|
||
{
|
||
// helper class
|
||
$pm = new Preprocessor_Model();
|
||
$ra_ip = server::remote_addr();
|
||
|
||
// boolean variable if user has active voip number (for menu rendering)
|
||
$this->user_has_voip = (bool) $pm->has_voip_sips($this->user_id);
|
||
|
||
// count of unread mail messages of user
|
||
$this->unread_user_mails = $pm->count_all_unread_inbox_messages_by_user_id($this->user_id);
|
||
|
||
// is this page favourite
|
||
$this->is_favourite = $pm->is_users_favourite($this->user_id, url_lang::current());
|
||
|
||
// gets account id of memeber (do not use Member_Model::ASSOCIATION here!)
|
||
if ($this->acl_check_view('Accounts_Controller', 'transfers', $this->member_id) &&
|
||
$this->member_id != 1)
|
||
{
|
||
$this->member_account_id = $pm->get_first_member_account_id($this->member_id);
|
||
}
|
||
|
||
// ip address span
|
||
$this->ip_address_span = $ra_ip;
|
||
|
||
// DZOLO (2011-09-05)
|
||
// This function is wery slow, when internet connection is off.
|
||
/*if (($ptr_record = dns::get_ptr_record($this->ip_address_span)) != '')
|
||
{
|
||
$this->ip_address_span .= ' <i>(' . $ptr_record . ')</i>';
|
||
}*/
|
||
|
||
// allowed subnets are enabled
|
||
if (Settings::get('allowed_subnets_enabled') && $this->member_id &&
|
||
$this->acl_check_edit(
|
||
'Allowed_subnets_Controller', 'allowed_subnet', $this->member_id
|
||
))
|
||
{
|
||
// toggle button between allowed subnets
|
||
$as = $pm->get_allowed_subnet_by_member_and_ip_address(
|
Také k dispozici: Unified diff
Nova branch pro reseni #921