Compare commits

..

7 Commits

Author SHA1 Message Date
Clemens Schwaighofer
605ea06bf0 Add additional_acl column to edit_access table
To be able to have special ACL (json) for edit edit access table too
2019-09-03 09:39:12 +09:00
Clemens Schwaighofer
9ec19f5940 Add list ACR, select update for html options JS, array methods in Basic
* ACR list has new list at level 10 for listing but not reading/opening
* JS update for the html options create
if select multi allow selected as array for highlight
* Basic Class
- array merge recursive implementation
proper implementation that proper merges nested arrays. With key is
always string override
- array flat per key
For multi arrays flatten down a key -> value entry to set the value to
the level up in the leaf
eg:
foo -> bar -> KEY: value
and you go by KEY as search it will change to
foo -> bar: value
2019-08-30 13:02:02 +09:00
Clemens Schwaighofer
a27e4603a8 Add deleted to edit_group/user decl, add assoc only return for fetchrow
DB IO Fetchrow has assoc only true/false
Currently only tested with PgSQL

default returns both,
if set true only returns assoc
2019-08-28 18:49:23 +09:00
Clemens Schwaighofer
54b7af348b Add fix for DB Array IO json error_check type field storage on empty save 2019-08-27 16:01:29 +09:00
Clemens Schwaighofer
c5d624a318 Add Additional ACL jsonb field to edit_pages table 2019-08-27 15:15:40 +09:00
Clemens Schwaighofer
47ffec1fd4 Add JSON additional ACL field to edit user page 2019-08-26 11:18:21 +09:00
Clemens Schwaighofer
72c6844e74 Jquery update to 3.4.1 2019-07-31 17:59:13 +09:00
20 changed files with 231 additions and 56 deletions

View File

@@ -51,6 +51,7 @@ INSERT INTO edit_page_menu_group VALUES ((SELECT edit_page_id FROM edit_page WHE
DELETE FROM edit_access_right;
INSERT INTO edit_access_right (name, level, type) VALUES ('Default', -1, 'default');
INSERT INTO edit_access_right (name, level, type) VALUES ('No Access', 0, 'none');
INSERT INTO edit_access_right (name, level, type) VALUES ('List', 10, 'list');
INSERT INTO edit_access_right (name, level, type) VALUES ('Read', 20, 'read');
INSERT INTO edit_access_right (name, level, type) VALUES ('Translator', 30, 'mod_trans');
INSERT INTO edit_access_right (name, level, type) VALUES ('Modify', 40, 'mod');

View File

@@ -14,5 +14,6 @@ CREATE TABLE edit_access (
uid VARCHAR,
enabled SMALLINT NOT NULL DEFAULT 0,
protected INT,
deleted SMALLINT DEFAULT 0
deleted SMALLINT DEFAULT 0,
additional_acl JSONB
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -10,8 +10,10 @@ CREATE TABLE edit_group (
edit_group_id SERIAL PRIMARY KEY,
name VARCHAR,
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT DEFAULT 0,
edit_scheme_id INT,
edit_access_right_id INT NOT NULL,
additional_acl JSONB,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -16,6 +16,7 @@ CREATE TABLE edit_user (
first_name_furigana VARCHAR,
last_name_furigana VARCHAR,
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT NOT NULL DEFAULT 0,
debug SMALLINT NOT NULL DEFAULT 0,
db_debug SMALLINT NOT NULL DEFAULT 0,
email VARCHAR,
@@ -32,6 +33,7 @@ CREATE TABLE edit_user (
locked SMALLINT DEFAULT 0,
password_change_date TIMESTAMP WITHOUT TIME ZONE, -- only when password is first set or changed
password_change_interval INTERVAL, -- null if no change is needed, or d/m/y time interval
additional_acl JSONB, -- additional ACL as JSON string (can be set by other pages)
FOREIGN KEY (connect_edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (edit_language_id) REFERENCES edit_language (edit_language_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,

View File

@@ -340,6 +340,7 @@ if ($form->my_page_name == 'edit_order') {
$elements[] = $form->formCreateElement("edit_language_id");
$elements[] = $form->formCreateElement("edit_scheme_id");
$elements[] = $form->formCreateElementListTable("edit_access_user");
$elements[] = $form->formCreateElement("additional_acl");
break;
case "edit_schemes":
$elements[] = $form->formCreateElement("enabled");
@@ -391,6 +392,7 @@ if ($form->my_page_name == 'edit_order') {
$elements[] = $form->formCreateElement("edit_access_right_id");
$elements[] = $form->formCreateElement("edit_scheme_id");
$elements[] = $form->formCreateElementListTable("edit_page_access");
$elements[] = $form->formCreateElement("additional_acl");
break;
case "edit_visible_group":
$elements[] = $form->formCreateElement("name");
@@ -409,6 +411,7 @@ if ($form->my_page_name == 'edit_order') {
$elements[] = $form->formCreateElement("description");
// add name/value list here
$elements[] = $form->formCreateElementListTable("edit_access_data");
$elements[] = $form->formCreateElement("additional_acl");
break;
default:
print "[No valid page definition given]";

View File

@@ -49,7 +49,15 @@ $edit_access = array (
"1" => "Yes",
"0" => "No"
)
)
),
"additional_acl" => array (
"value" => $GLOBALS["additional_acl"],
"output_name" => "Additional ACL (as JSON)",
"type" => "textarea",
"error_check" => "json",
"rows" => 10,
"cols" => 60
),
),
"table_name" => "edit_access",
"load_query" => "SELECT edit_access_id, name FROM edit_access ORDER BY name",

View File

@@ -37,7 +37,15 @@ $edit_groups = array (
"int_null" => 1,
"type" => "drop_down_db",
"query" => "SELECT edit_scheme_id, name FROM edit_scheme WHERE enabled = 1 ORDER BY name"
)
),
"additional_acl" => array (
"value" => $GLOBALS["additional_acl"],
"output_name" => "Additional ACL (as JSON)",
"type" => "textarea",
"error_check" => "json",
"rows" => 10,
"cols" => 60
),
),
"load_query" => "SELECT edit_group_id, name, enabled FROM edit_group ORDER BY name",
"table_name" => "edit_group",

View File

@@ -103,7 +103,8 @@ $edit_users = array (
"email" => array (
"value" => $GLOBALS["email"],
"output_name" => "E-Mail",
"type" => "text"
"type" => "text",
"error_check" => "email"
),
"last_name" => array (
"value" => $GLOBALS["last_name"],
@@ -173,7 +174,15 @@ $edit_users = array (
"1" => "Yes",
"0" => "No"
)
)
),
"additional_acl" => array (
"value" => $GLOBALS["additional_acl"],
"output_name" => "Additional ACL (as JSON)",
"type" => "textarea",
"error_check" => "json",
"rows" => 10,
"cols" => 60
),
),
"load_query" => "SELECT edit_user_id, username, enabled, debug, db_debug, strict, locked, login_error_count FROM edit_user ORDER BY username",
"table_name" => "edit_user",

View File

@@ -605,15 +605,16 @@ function html_options(name, data, selected = '', options_only = false, return_st
// NOTE : USE THIS CALL, the above one is deprecated
// METHOD: html_options
// PARAMS: name/id, array for the options,
// selected item uid
// multiple [def false] if this is true, the drop down will be turned into multiple select
// selected item uid [drop down string, multi select array]
// multiple [def 0] if this is 1 or larger, the drop down will be turned into multiple select
// the number sets the size value unless it is 1, then it is default
// options_only [def false] if this is true, it will not print the select part
// return_string [def false]: return as string and not as element
// sort [def '']: if empty as is, else allowed 'keys', 'values' all others are ignored
// RETURN: html with build options block
// DESC : creates an select/options drop down block.
// the array needs to be key -> value format. key is for the option id and value is for the data output
function html_options_block(name, data, selected = '', multiple = false, options_only = false, return_string = false, sort = '')
function html_options_block(name, data, selected = '', multiple = 0, options_only = false, return_string = false, sort = '')
{
var content = [];
var element_select;
@@ -622,8 +623,11 @@ function html_options_block(name, data, selected = '', multiple = false, options
var data_list = []; // for sorted output
var value;
var option;
if (multiple === true) {
if (multiple > 0) {
select_options.multiple = '';
if (multiple > 1) {
select_options.size = multiple;
}
}
// set outside select, gets stripped on return if options only is true
element_select = cel('select', name, '', [], select_options);
@@ -640,14 +644,18 @@ function html_options_block(name, data, selected = '', multiple = false, options
// for (const [key, value] of Object.entries(data)) {
for (const key of data_list) {
value = data[key];
console.log('create [%s] options: key: %s, value: %s', name, key, value);
// console.log('create [%s] options: key: %s, value: %s', name, key, value);
// basic options init
options = {
'label': value,
'value': key
};
// add selected if matching
if (selected == key) {
if (multiple == 0 && !Array.isArray(selected) && selected == key) {
options.selected = '';
}
// for multiple, we match selected as array
if (multiple == 1 && Array.isArray(selected) && selected.indexOf(key) != -1) {
options.selected = '';
}
// create the element option

View File

@@ -683,15 +683,16 @@ function html_options(name, data, selected = '', options_only = false, return_st
// NOTE : USE THIS CALL, the above one is deprecated
// METHOD: html_options
// PARAMS: name/id, array for the options,
// selected item uid
// multiple [def false] if this is true, the drop down will be turned into multiple select
// selected item uid [drop down string, multi select array]
// multiple [def 0] if this is 1 or larger, the drop down will be turned into multiple select
// the number sets the size value unless it is 1, then it is default
// options_only [def false] if this is true, it will not print the select part
// return_string [def false]: return as string and not as element
// sort [def '']: if empty as is, else allowed 'keys', 'values' all others are ignored
// RETURN: html with build options block
// DESC : creates an select/options drop down block.
// the array needs to be key -> value format. key is for the option id and value is for the data output
function html_options_block(name, data, selected = '', multiple = false, options_only = false, return_string = false, sort = '')
function html_options_block(name, data, selected = '', multiple = 0, options_only = false, return_string = false, sort = '')
{
var content = [];
var element_select;
@@ -700,8 +701,11 @@ function html_options_block(name, data, selected = '', multiple = false, options
var data_list = []; // for sorted output
var value;
var option;
if (multiple === true) {
if (multiple > 0) {
select_options.multiple = '';
if (multiple > 1) {
select_options.size = multiple;
}
}
// set outside select, gets stripped on return if options only is true
element_select = cel('select', name, '', [], select_options);
@@ -718,14 +722,18 @@ function html_options_block(name, data, selected = '', multiple = false, options
// for (const [key, value] of Object.entries(data)) {
for (const key of data_list) {
value = data[key];
console.log('create [%s] options: key: %s, value: %s', name, key, value);
// console.log('create [%s] options: key: %s, value: %s', name, key, value);
// basic options init
options = {
'label': value,
'value': key
};
// add selected if matching
if (selected == key) {
if (multiple == 0 && !Array.isArray(selected) && selected == key) {
options.selected = '';
}
// for multiple, we match selected as array
if (multiple == 1 && Array.isArray(selected) && selected.indexOf(key) != -1) {
options.selected = '';
}
// create the element option

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
/*!
* jQuery JavaScript Library v3.4.0
* jQuery JavaScript Library v3.4.1
* https://jquery.com/
*
* Includes Sizzle.js
@@ -9,7 +9,7 @@
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2019-04-10T19:48Z
* Date: 2019-05-01T21:04Z
*/
( function( global, factory ) {
@@ -142,7 +142,7 @@ function toType( obj ) {
var
version = "3.4.0",
version = "3.4.1",
// Define a local copy of jQuery
jQuery = function( selector, context ) {
@@ -4498,8 +4498,12 @@ var documentElement = document.documentElement;
},
composed = { composed: true };
// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
// Check attachment across shadow DOM boundaries when possible (gh-3504)
if ( documentElement.attachShadow ) {
// Support: iOS 10.0-10.2 only
// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
// leading to errors. We need to check for `getRootNode`.
if ( documentElement.getRootNode ) {
isAttached = function( elem ) {
return jQuery.contains( elem.ownerDocument, elem ) ||
elem.getRootNode( composed ) === elem.ownerDocument;
@@ -5359,8 +5363,7 @@ jQuery.event = {
// Claim the first handler
if ( rcheckableType.test( el.type ) &&
el.click && nodeName( el, "input" ) &&
dataPriv.get( el, "click" ) === undefined ) {
el.click && nodeName( el, "input" ) ) {
// dataPriv.set( el, "click", ... )
leverageNative( el, "click", returnTrue );
@@ -5377,8 +5380,7 @@ jQuery.event = {
// Force setup before triggering a click
if ( rcheckableType.test( el.type ) &&
el.click && nodeName( el, "input" ) &&
dataPriv.get( el, "click" ) === undefined ) {
el.click && nodeName( el, "input" ) ) {
leverageNative( el, "click" );
}
@@ -5419,7 +5421,9 @@ function leverageNative( el, type, expectSync ) {
// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
if ( !expectSync ) {
jQuery.event.add( el, type, returnTrue );
if ( dataPriv.get( el, type ) === undefined ) {
jQuery.event.add( el, type, returnTrue );
}
return;
}
@@ -5434,9 +5438,13 @@ function leverageNative( el, type, expectSync ) {
if ( ( event.isTrigger & 1 ) && this[ type ] ) {
// Interrupt processing of the outer synthetic .trigger()ed event
if ( !saved ) {
// Saved data should be false in such cases, but might be a leftover capture object
// from an async native handler (gh-4350)
if ( !saved.length ) {
// Store arguments for use when handling the inner native event
// There will always be at least one argument (an event object), so this array
// will not be confused with a leftover capture object.
saved = slice.call( arguments );
dataPriv.set( this, type, saved );
@@ -5449,14 +5457,14 @@ function leverageNative( el, type, expectSync ) {
if ( saved !== result || notAsync ) {
dataPriv.set( this, type, false );
} else {
result = undefined;
result = {};
}
if ( saved !== result ) {
// Cancel the outer synthetic event
event.stopImmediatePropagation();
event.preventDefault();
return result;
return result.value;
}
// If this is an inner synthetic event for an event with a bubbling surrogate
@@ -5471,17 +5479,19 @@ function leverageNative( el, type, expectSync ) {
// If this is a native event triggered above, everything is now in order
// Fire an inner synthetic event with the original arguments
} else if ( saved ) {
} else if ( saved.length ) {
// ...and capture the result
dataPriv.set( this, type, jQuery.event.trigger(
dataPriv.set( this, type, {
value: jQuery.event.trigger(
// Support: IE <=9 - 11+
// Extend with the prototype to reset the above stopImmediatePropagation()
jQuery.extend( saved.shift(), jQuery.Event.prototype ),
saved,
this
) );
// Support: IE <=9 - 11+
// Extend with the prototype to reset the above stopImmediatePropagation()
jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
saved.slice( 1 ),
this
)
} );
// Abort handling of the native event
event.stopImmediatePropagation();

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
jquery-3.4.0.js
jquery-3.4.1.js

View File

@@ -1 +1 @@
jquery-3.4.0.min.js
jquery-3.4.1.min.js

View File

@@ -442,7 +442,7 @@ class Basic
// on second call it sends the end time and then also prints the running time
public function runningTime($simple = false)
{
list($micro, $timestamp) = explode(" ", microtime());
list($micro, $timestamp) = explode(' ', microtime());
$string = '';
$running_time = '';
if (!$this->starttime) {
@@ -1088,6 +1088,84 @@ class Basic
return false;
}
// METHOD: arrayMergeRecursive
// PARAMS: array, array, ..., true/false flag how to handle key
// key flag: true: handle keys as string or int, default false: all keys are string
// RETURN: merged array
// DESC : correctly recursive merges as an array as array_merge_recursive just glues things together
public static function arrayMergeRecursive()
{
// croak on not enough arguemnts (we need at least two)
if (func_num_args() < 2) {
trigger_error(__FUNCTION__ .' needs two or more array arguments', E_USER_WARNING);
return;
}
// default key is not string
$key_is_string = false;
$arrays = func_get_args();
// if last is not array, then assume it is trigger for key is always string
if (!is_array(end($arrays))) {
if (array_pop($arrays)) {
$key_is_string = true;
}
}
// check that arrays count is at least two, else we don't have enough to do anything
if (count($arrays) < 2) {
trigger_error(__FUNCTION__.' needs two or more array arguments', E_USER_WARNING);
return;
}
$merged = array();
while ($arrays) {
$array = array_shift($arrays);
if (!is_array($array)) {
trigger_error(__FUNCTION__ .' encountered a non array argument', E_USER_WARNING);
return;
}
if (!$array) {
continue;
}
foreach ($array as $key => $value) {
// if string or if key is assumed to be string do key match else add new entry
if (is_string($key) || $key_is_string === false) {
if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key])) {
// $merged[$key] = call_user_func(__METHOD__, $merged[$key], $value, $key_is_string);
$merged[$key] = Basic::arrayMergeRecursive($merged[$key], $value, $key_is_string);
} else {
$merged[$key] = $value;
}
} else {
$merged[] = $value;
}
}
}
return $merged;
}
// METHOD: arrayFlatForKey
// PARAMS: array (nested)
// search, key to find that has no sub leaf and will be pushed up
// RETURN: modified array
// DESC : searches for key -> value in an array tree and writes the value one level up
// this will remove this leaf will all other values
public static function arrayFlatForKey($array, $search)
{
foreach ($array as $key => $value) {
// if it is not an array do just nothing
if (is_array($value)) {
// probe it has search key
if (isset($value[$search])) {
// set as current
$array[$key] = $value[$search];
} else {
// call up next node down
// $array[$key] = call_user_func(__METHOD__, $value, $search);
$array[$key] = Basic::arrayFlatForKey($value, $search);
}
}
}
return $array;
}
// METHOD: inArrayAny
// WAS : in_array_any
// PARAMS: needle: array

View File

@@ -334,7 +334,7 @@ class ArrayIO extends \CoreLibs\DB\IO
$q_vars = '';
$q_where = '';
foreach ($this->table_array as $column => $data_array) {
/********************************* START FILE *************************************/
/********************************* START FILE *************************************/
// file upload
if ($this->table_array[$column]['file']) {
// falls was im tmp drinnen, sprich ein upload, datei kopieren, Dateinamen in db schreiben
@@ -381,7 +381,7 @@ class ArrayIO extends \CoreLibs\DB\IO
}
} // delete or upload
} // file IF
/********************************* END FILE **************************************/
/********************************* END FILE **************************************/
// do not write 'pk' (primary key) or 'view' values
if (!$this->table_array[$column]['pk'] && $this->table_array[$column]['type'] != 'view' && strlen($column) > 0) {
@@ -425,15 +425,21 @@ class ArrayIO extends \CoreLibs\DB\IO
}
$q_data .= $_value;
} else {
// normal string
$q_data .= "'";
// if add slashes do convert & add slashes else write AS is
if ($addslashes) {
$q_data .= $this->dbEscapeString($this->convertEntities($this->table_array[$column]['value']));
// if the error check is json, we set field to null if NOT set
// else normal string write
if ($this->table_array[$column]['error_check'] == 'json' && !$this->table_array[$column]['value']) {
$q_data .= 'NULL';
} else {
$q_data .= $this->dbEscapeString($this->table_array[$column]['value']);
// normal string
$q_data .= "'";
// if add slashes do convert & add slashes else write AS is
if ($addslashes) {
$q_data .= $this->dbEscapeString($this->convertEntities($this->table_array[$column]['value']));
} else {
$q_data .= $this->dbEscapeString($this->table_array[$column]['value']);
}
$q_data .= "'";
}
$q_data .= "'";
}
}
} // while ...

View File

@@ -1259,9 +1259,10 @@ class IO extends \CoreLibs\Basic
// WAS : db_fetch_array
// PARAMS: cusors -> the cursor from db_exec or pg_query/pg_exec/mysql_query
// if not set will use internal cursor, if not found, stops with 0 (error)
// assoc_only -> false is default, if true only assoc rows
// RETURN: a mixed row
// DESC : executes a cursor and returns the data, if no more data 0 will be returned
public function dbFetchArray($cursor = 0)
public function dbFetchArray($cursor = 0, $assoc_only = false)
{
// return false if no query or cursor set ...
if (!$cursor) {
@@ -1272,15 +1273,21 @@ class IO extends \CoreLibs\Basic
$this->__dbError();
return false;
}
return $this->__dbConvertEncoding($this->db_functions->__dbFetchArray($cursor));
return $this->__dbConvertEncoding(
$this->db_functions->__dbFetchArray(
$cursor,
$this->db_functions->__dbResultType($assoc_only)
)
);
}
// METHOD: dbReturnRow
// WAS : db_return_row
// PARAMS: query -> the query to be executed
// assoc_only -> if true, only return assoc entry, else both (pgsql)
// RETURN: mixed db result
// DESC : returns the FIRST row of the given query
public function dbReturnRow($query)
public function dbReturnRow($query, $assoc_only = false)
{
if (!$query) {
$this->error_id = 11;
@@ -1294,7 +1301,7 @@ class IO extends \CoreLibs\Basic
return false;
}
$cursor = $this->dbExec($query);
$result = $this->dbFetchArray($cursor);
$result = $this->dbFetchArray($cursor, $assoc_only);
return $result;
}

View File

@@ -190,6 +190,9 @@ class PgSQL
// DESC : wrapper for pg_fetch_array
public function __dbFetchArray($cursor, $result_type = '')
{
if ($result_type == true) {
$result_type = PGSQL_ASSOC;
}
// result type is passed on as is [should be checked]
if ($result_type) {
return pg_fetch_array($cursor, null, $result_type);
@@ -198,6 +201,18 @@ class PgSQL
}
}
// METHOD: __dbResultType
// PARAMS: true/false for ASSOC only or BOTH
// RETURN: PGSQL assoc type
// DESC : simple match up between assoc true/false
public function __dbResultType($assoc_type)
{
if ($assoc_type == true) {
return PGSQL_ASSOC;
}
return ''; // fallback to default
}
// METHOD: __dbFetchAll
// WAS : _db_fetch_all
// PARAMS: cursor

View File

@@ -844,6 +844,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
//if ($value['mandatory'] && $value['error_check'])
// if error value set && somethign input, check if input okay
if ($value['error_check'] && $this->table_array[$key]['value']) {
$this->debug('ERROR CHECK', 'Key: '.$key.' => '.$value['error_check']);
// each error check can be a piped seperated value, lets split it
// $this->debug('edit', $value['error_check']);
foreach (explode('|', $value['error_check']) as $error_check) {
@@ -918,6 +919,14 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// error
}
break;
case 'json':
// check if valid json
$json_out = json_decode($this->table_array[$key]['value'], true);
$this->debug('JSON ENCODE', 'LAST ERROR: '.json_last_error());
if (json_last_error()) {
$this->msg .= sprintf($this->l->__('Please enter a valid JSON string for the field <b>%s<b>: %s'), $this->table_array[$key]['output_name'], json_last_error_msg());
}
break;
} // switch
} // for each error to check
} elseif ($value['mandatory'] &&
@@ -1585,7 +1594,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
if ($data_array['type'] == 'drop_down_db') {
$md_q = md5($data_array['query']);
while ($res = $this->dbReturn($data_array['query'])) {
$this->debug('edit', 'Q[$md_q] pos: '.$this->cursor_ext[$md_q]['pos'].' | want: '.$data_array['preset'].' | set: '.$data['preset'][$el_name]);
$this->debug('edit', 'Q['.$md_q.'] pos: '.$this->cursor_ext[$md_q]['pos'].' | want: '.$data_array['preset'].' | set: '.$data['preset'][$el_name]);
// first is default for this element
if (!$data['preset'][$el_name] && ($this->cursor_ext[$md_q]['pos'] == $data_array['preset'])) {
$data['preset'][$el_name] = $res[0];