mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
WIP admin history: using eTemplate tree instead of regexp to parse labels and selectbox values
This commit is contained in:
parent
6e5fbbba7e
commit
fa8ee606b3
@ -1296,6 +1296,40 @@ abstract class admin_cmd
|
||||
return Api\Auth::randomstring($len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of eTemplate used to make the change to derive UI for history
|
||||
*
|
||||
* @return string|null etemplate name
|
||||
*/
|
||||
protected function get_etemplate_name()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return eTemplate used to make the change to derive UI for history
|
||||
*
|
||||
* @return Api\Etemplate|null
|
||||
*/
|
||||
protected function get_etemplate()
|
||||
{
|
||||
static $tpl = null; // some caching to not instanciate it twice
|
||||
|
||||
if (!isset($tpl))
|
||||
{
|
||||
$name = $this->get_etemplate_name();
|
||||
if (empty($name))
|
||||
{
|
||||
$tpl = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tpl = Api\Etemplate::instance($name);
|
||||
}
|
||||
}
|
||||
return $tpl ? $tpl : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return (human readable) labels for keys of changes
|
||||
*
|
||||
@ -1303,71 +1337,82 @@ abstract class admin_cmd
|
||||
*/
|
||||
function get_change_labels()
|
||||
{
|
||||
return [];
|
||||
$labels = [];
|
||||
$label = null;
|
||||
if (($tpl = $this->get_etemplate()))
|
||||
{
|
||||
$tpl->run(function($cname, $expand, $widget) use (&$labels, &$label)
|
||||
{
|
||||
switch($widget->type)
|
||||
{
|
||||
// remember label from last description widget
|
||||
case 'description':
|
||||
if (!empty($widget->attrs['value'])) $label = $widget->attrs['value'];
|
||||
break;
|
||||
// ignore non input-widgets
|
||||
case 'hbox': case 'vbox': case 'box': case 'groupbox':
|
||||
case 'grid': case 'columns': case 'column': case 'rows': case 'row':
|
||||
case 'template': case 'tabbox': case 'tabs': case 'tab':
|
||||
// ignore buttons too
|
||||
case 'button':
|
||||
break;
|
||||
default:
|
||||
if (!empty($widget->id))
|
||||
{
|
||||
if (!empty($widget->attrs['label'])) $label = $widget->attrs['label'];
|
||||
$labels[$widget->id] = $label;
|
||||
$label = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
unset($cname, $expand);
|
||||
}, ['', []]);
|
||||
}
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return widget types (indexed by field key) for changes
|
||||
*
|
||||
* Used by historylog widget to show the changes the command recorded.
|
||||
*/
|
||||
function get_change_widgets()
|
||||
{
|
||||
// TODO: Some kind of regex?
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read change labels from descriptions in template:
|
||||
* - <description value="Expires" for="account_expires"/>
|
||||
* - <description value="Label"/>\n<widget id="id"/>
|
||||
* - <checkbox id="account_status" selected_value="A" label="Account active"/>
|
||||
* @param type $name
|
||||
*/
|
||||
protected function change_labels_from_template($name)
|
||||
{
|
||||
$labels = [];
|
||||
$matches = null;
|
||||
if (($path = Api\Etemplate::relPath($name)) &&
|
||||
($tpl = file_get_contents(Api\Etemplate::rel2path($path))))
|
||||
$widgets = [];
|
||||
$last_select = null;
|
||||
if (($tpl = $this->get_etemplate()))
|
||||
{
|
||||
if (preg_match_all('/<description.*value="([^"]+)".*\n?.*(for|id)="([^"]+)"/sU', $tpl, $matches, PREG_PATTERN_ORDER))
|
||||
$tpl->run(function($cname, $expand, $widget) use (&$widgets, &$last_select)
|
||||
{
|
||||
foreach($matches[1] as $key => $name)
|
||||
switch($widget->type)
|
||||
{
|
||||
$id = $matches[3][$key];
|
||||
$label= $matches[1][$key];
|
||||
if (!empty($id) && !empty($label))
|
||||
{
|
||||
$labels[$id] = $label;
|
||||
}
|
||||
// ignore non input-widgets
|
||||
case 'hbox': case 'vbox': case 'box': case 'groupbox':
|
||||
case 'grid': case 'columns': case 'column': case 'rows': case 'row':
|
||||
case 'template': case 'tabbox': case 'tabs': case 'tab':
|
||||
// ignore buttons too
|
||||
case 'button':
|
||||
break;
|
||||
// config templates have options in the template
|
||||
case 'option':
|
||||
if (!is_array($widgets[$last_select])) $widgets[$last_select] = [];
|
||||
$widgets[$last_select][(string)$widget->attrs['value']] = $widget->attrs['#text'];
|
||||
break;
|
||||
default:
|
||||
$last_select = null;
|
||||
if (!empty($widget->id))
|
||||
{
|
||||
$widgets[$widget->id] = $widget->type;
|
||||
if (in_array($widget->type, ['select']))
|
||||
{
|
||||
$last_select = $widget->id;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (preg_match_all('/<(checkbox).*(label|id)="([^"]+)".*(label|id)="([^"]+)"/', $tpl, $matches, PREG_PATTERN_ORDER))
|
||||
{
|
||||
foreach($matches[2] as $key => $name)
|
||||
{
|
||||
$id = $name === 'id' ? $matches[3][$key] : $matches[5][$key];
|
||||
$label= $name === 'id' ? $matches[5][$key] : $matches[3][$key];
|
||||
if (!empty($id) && !empty($label))
|
||||
{
|
||||
$labels[$id] = $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (preg_match_all('/<(int|float).*(label|id)="([^"]+)".*(label|id)="([^"]+)"/', $tpl, $matches, PREG_PATTERN_ORDER))
|
||||
{
|
||||
foreach($matches[2] as $key => $name)
|
||||
{
|
||||
$id = $name === 'id' ? $matches[3][$key] : $matches[5][$key];
|
||||
$label= $name === 'id' ? $matches[5][$key] : $matches[3][$key];
|
||||
if (!empty($id) && !empty($label))
|
||||
{
|
||||
$labels[$id] = $label;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($cname, $expand);
|
||||
}, ['', []]);
|
||||
}
|
||||
error_log(__METHOD__."($name) path=$path returning ".json_encode($labels));
|
||||
return $labels;
|
||||
return $widgets;
|
||||
}
|
||||
}
|
||||
|
@ -87,17 +87,27 @@ class admin_cmd_config extends admin_cmd
|
||||
lang($this->appname ? $this->appname : $this->app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name of eTemplate used to make the change to derive UI for history
|
||||
*
|
||||
* @return string|null etemplate name
|
||||
*/
|
||||
function get_etemplate_name()
|
||||
{
|
||||
return ($this->appname ? $this->appname : $this->app).'.config';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return (human readable) labels for keys of changes
|
||||
*
|
||||
* Reading them from admin.account template
|
||||
* Reimplemented to get ride of "newsettins" namespace
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_change_labels()
|
||||
{
|
||||
$labels = [];
|
||||
foreach($this->change_labels_from_template(($this->appname ? $this->appname : $this->app).'.config') as $id => $label)
|
||||
foreach(parent::get_change_labels() as $id => $label)
|
||||
{
|
||||
if (strpos($id, 'newsettings[') === 0)
|
||||
{
|
||||
@ -106,4 +116,24 @@ class admin_cmd_config extends admin_cmd
|
||||
}
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return widgets for keys of changes
|
||||
*
|
||||
* Reimplemented to get ride of "newsettins" namespace
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_change_widgets()
|
||||
{
|
||||
$widgets = [];
|
||||
foreach(parent::get_change_widgets() as $id => $widget)
|
||||
{
|
||||
if (strpos($id, 'newsettings[') === 0)
|
||||
{
|
||||
$widgets[substr($id, 12, -1)] = $widget;
|
||||
}
|
||||
}
|
||||
return $widgets;
|
||||
}
|
||||
}
|
||||
|
@ -210,12 +210,83 @@ class admin_cmd_delete_account extends admin_cmd
|
||||
}
|
||||
|
||||
/**
|
||||
* Return (human readable) labels for keys of changes
|
||||
*
|
||||
* Reading them from admin.account template
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function get_etemplate_name()
|
||||
{
|
||||
return $this->is_user ? 'admin.account':
|
||||
($GLOBALS['egw_info']['apps']['stylite'] ? 'stylite' : 'groups').'.group.edit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return widget types (indexed by field key) for changes
|
||||
*
|
||||
* Used by historylog widget to show the changes the command recorded.
|
||||
*/
|
||||
function get_change_labels()
|
||||
{
|
||||
$widgets = parent::get_change_labels();
|
||||
|
||||
$widgets['account_id'] = 'numerical ID'; // normaly not displayed
|
||||
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return widget types (indexed by field key) for changes
|
||||
*
|
||||
* Used by historylog widget to show the changes the command recorded.
|
||||
*/
|
||||
function get_change_widgets()
|
||||
{
|
||||
$widgets = parent::get_change_widgets();
|
||||
|
||||
$widgets['account_id'] = 'integer'; // normaly not displayed
|
||||
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the whole object-data as array, it's a cast of the object to an array
|
||||
*
|
||||
* Reimplement to supress data not relevant for groups, but historically stored
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function as_array()
|
||||
{
|
||||
$data = parent::as_array();
|
||||
|
||||
if (!$this->is_user)
|
||||
{
|
||||
$data['old'] = array_diff_key($data['old'], array_flip([
|
||||
'account_pwd', 'account_status',
|
||||
'account_expires', 'account_primary_group',
|
||||
'account_lastlogin', 'account_lastloginfrom',
|
||||
'account_lastpwd_change', 'members-active',
|
||||
'account_firstname', 'account_lastname', 'account_fullname',
|
||||
]));
|
||||
}
|
||||
unset($data['old']['account_type']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
}
|
||||
* Return a title / string representation for a given command, eg. to display it
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function __tostring()
|
||||
{
|
||||
return lang('Delete account %1',admin_cmd::display_account($this->account));
|
||||
return lang('Delete account %1',
|
||||
// use own data to display deleted name of user/group
|
||||
$this->old['account_lid'] ? ($this->is_user ? lang('User') : lang('Group')).' '.$this->old['account_lid'] :
|
||||
admin_cmd::display_account($this->account));
|
||||
}
|
||||
}
|
||||
|
@ -225,36 +225,13 @@ class admin_cmd_edit_user extends admin_cmd_change_pw
|
||||
}
|
||||
|
||||
/**
|
||||
* Return (human readable) labels for keys of changes
|
||||
* Get name of eTemplate used to make the change to derive UI for history
|
||||
*
|
||||
* Reading them from admin.account template
|
||||
*
|
||||
* @return array
|
||||
* @return string|null etemplate name
|
||||
*/
|
||||
function get_change_labels()
|
||||
function get_etemplate_name()
|
||||
{
|
||||
$labels = $this->change_labels_from_template('admin.account');
|
||||
$labels += array(
|
||||
'account_firstname' => 'First name',
|
||||
'account_lastname' => 'Last name',
|
||||
'account_email' => 'Email',
|
||||
'account_passwd_2' => false
|
||||
);
|
||||
return $labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of widgets to use for displaying changes
|
||||
*/
|
||||
function get_change_widgets() {
|
||||
$widgets = parent::get_change_widgets();
|
||||
|
||||
$widgets += array(
|
||||
'account_primary_group' => 'select-account',
|
||||
'account_groups' => 'select-account',
|
||||
'account_expires' => 'date-time'
|
||||
);
|
||||
return $widgets;
|
||||
return 'admin.account';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2985,7 +2985,7 @@ var et2_nextmatch_header_bar = (function(){ "use strict"; return et2_DOMWidget.e
|
||||
value[_widget.id] = _widget._oldValue = _widget.getValue();
|
||||
var mgr = new et2_arrayMgr(value);
|
||||
jQuery.extend(true, this.nextmatch.activeFilters,mgr.data);
|
||||
}
|
||||
};
|
||||
if(sub_header.instanceOf(et2_inputWidget))
|
||||
{
|
||||
bind_change.call(this, sub_header);
|
||||
|
@ -91,7 +91,10 @@ class Request
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data=array();
|
||||
protected $data=[
|
||||
'content' => [],
|
||||
'readonlys' => [],
|
||||
];
|
||||
/**
|
||||
* Flag if data has been modified and therefor need to be stored again in the session
|
||||
*
|
||||
|
@ -129,6 +129,11 @@ class Widget
|
||||
{
|
||||
$this->children[] = self::factory($reader->name, $reader, $reader->getAttribute('id'));
|
||||
}
|
||||
// read eg. option content to "#text"
|
||||
if ($reader->nodeType == XMLReader::TEXT)
|
||||
{
|
||||
$this->attrs[(string)$reader->name] = (string)$reader->value;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset content as we leave
|
||||
@ -508,7 +513,7 @@ class Widget
|
||||
*
|
||||
* Default implementation only calls method on itself and run on all children
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be the cname, second $expand!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
*/
|
||||
@ -547,6 +552,12 @@ class Widget
|
||||
}
|
||||
if($call) call_user_func_array(array($this, $method_name), $params);
|
||||
}
|
||||
// allow calling with a function or closure --> call it with widget as first param
|
||||
elseif (is_callable($method_name))
|
||||
{
|
||||
$params[2] = $this;
|
||||
call_user_func_array($method_name, $params);
|
||||
}
|
||||
foreach($this->children as $child)
|
||||
{
|
||||
// If type has something that can be expanded, we need to expand it so the correct method is run
|
||||
|
@ -38,7 +38,7 @@ class Box extends Etemplate\Widget
|
||||
* Reimplemented because grids and boxes can have an own namespace.
|
||||
* GroupBox has no namespace!
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be cname!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
*/
|
||||
@ -64,6 +64,12 @@ class Box extends Etemplate\Widget
|
||||
{
|
||||
call_user_func_array(array($this, $method_name), $params);
|
||||
}
|
||||
// allow calling with a function or closure --> call it with widget as first param
|
||||
elseif (is_callable($method_name))
|
||||
{
|
||||
$params[2] = $this;
|
||||
call_user_func_array($method_name, $params);
|
||||
}
|
||||
|
||||
// Expand children
|
||||
$columns_disabled = null;
|
||||
|
@ -60,7 +60,7 @@ class Grid extends Box
|
||||
* - row run method checks now for each child (arbitrary widget) if it the column's key is included in $columns_disabled
|
||||
* - as a grid can contain other grid's as direct child, we have to backup and initialise $columns_disabled in grid run!
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be the cname, second $expand!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
* @param array $columns_disabled=array() disabled columns
|
||||
@ -99,6 +99,12 @@ class Grid extends Box
|
||||
{
|
||||
call_user_func_array(array($this, $method_name), $params);
|
||||
}
|
||||
// allow calling with a function or closure --> call it with widget as first param
|
||||
elseif (is_callable($method_name))
|
||||
{
|
||||
$params[2] = $this;
|
||||
call_user_func_array($method_name, $params);
|
||||
}
|
||||
//foreach($this->children as $n => $child)
|
||||
$repeat_child = null;
|
||||
for($n = 0; ; ++$n)
|
||||
|
@ -1204,7 +1204,7 @@ class Nextmatch extends Etemplate\Widget
|
||||
*
|
||||
* Reimplemented to add namespace, and make sure row template gets included
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be cname, second $expand!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
*/
|
||||
|
@ -38,7 +38,7 @@ class Tabbox extends Etemplate\Widget
|
||||
* Overridden here to apply readonlys for the tabbox to disabled on the tab
|
||||
* content. This prevents running the method on disabled tabs.
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be the cname, second $expand!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
*/
|
||||
@ -91,7 +91,7 @@ class Tabbox extends Etemplate\Widget
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($respect_disabled && $readonlys)
|
||||
{
|
||||
foreach($this->children[1]->children as $tab)
|
||||
|
@ -234,7 +234,7 @@ class Template extends Etemplate\Widget
|
||||
*
|
||||
* Reimplemented because templates can have an own namespace specified in attrs[content], NOT id!
|
||||
*
|
||||
* @param string $method_name
|
||||
* @param string|callable $method_name or function($cname, $expand, $widget)
|
||||
* @param array $params =array('') parameter(s) first parameter has to be cname, second $expand!
|
||||
* @param boolean $respect_disabled =false false (default): ignore disabled, true: method is NOT run for disabled widgets AND their children
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user