Compare commits

..

10 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
Clemens Schwaighofer
d0753512a3 Fix path calls, add better js html options block
in admin set paths, only call smarty sets if smarty object is initalized

Add better JS html options creation with multi block allow. Old call is
still there as wrapper to new call html_options_block

missing variable init in Class Basic
2019-07-31 15:36:28 +09:00
Clemens Schwaighofer
d0de3821f8 Basic class date diff calc fix for including last day 2019-07-08 12:02:15 +09:00
Clemens Schwaighofer
0d89eea1af Basic class fix for calc interval, smarty test page fix
- smarty test page used old variable names
- the interval date calc function was private but should be public
static
2019-06-28 11:50:40 +09:00
23 changed files with 354 additions and 63 deletions

1
.phplint-cache Normal file

File diff suppressed because one or more lines are too long

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

@@ -16,10 +16,10 @@ $CSS_NAME = 'smart_test.css';
$USE_PROTOTYPE = false;
$USE_JQUERY = true;
if ($USE_PROTOTYPE) {
$EDIT_JAVASCRIPT = 'edit.pt.js';
$ADMIN_JAVASCRIPT = 'edit.pt.js';
$JS_NAME = 'prototype.test.js';
} else if ($USE_JQUERY) {
$EDIT_JAVASCRIPT = 'edit.jq.js';
} elseif ($USE_JQUERY) {
$ADMIN_JAVASCRIPT = 'edit.jq.js';
$JS_NAME = 'jquery.test.js';
}
$PAGE_WIDTH = "100%";

View File

@@ -106,13 +106,15 @@ if (!$AJAX_PAGE) {
if (file_exists($cms->javascript.$cms->JS_SPECIAL_TEMPLATE_NAME) && is_file($cms->javascript.$cms->JS_SPECIAL_TEMPLATE_NAME)) {
$cms->JS_SPECIAL_INCLUDE = $cms->javascript.$cms->JS_SPECIAL_TEMPLATE_NAME;
}
// check if template names exist
if (!file_exists($smarty->getTemplateDir()[0].DS.$MASTER_TEMPLATE_NAME)) {
// abort if master template could not be found
exit('MASTER TEMPLATE: '.$MASTER_TEMPLATE_NAME.' could not be found');
}
if (isset($TEMPLATE_NAME) && !file_exists($smarty->getTemplateDir()[0].DS.$TEMPLATE_NAME)) {
exit('INCLUDE TEMPLATE: '.$TEMPLATE_NAME.' could not be found');
if ($smarty) {
// check if template names exist
if (!file_exists($smarty->getTemplateDir()[0].DS.$MASTER_TEMPLATE_NAME)) {
// abort if master template could not be found
exit('MASTER TEMPLATE: '.$MASTER_TEMPLATE_NAME.' could not be found');
}
if (isset($TEMPLATE_NAME) && !file_exists($smarty->getTemplateDir()[0].DS.$TEMPLATE_NAME)) {
exit('INCLUDE TEMPLATE: '.$TEMPLATE_NAME.' could not be found');
}
}
}

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

@@ -221,6 +221,38 @@ function getTimestamp()
return date.getTime();
}
// METHOD: dec2hex
// PARAMS: decimal string
// RETURN: string
// DESC : dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex(dec)
{
return ('0' + dec.toString(16)).substr(-2);
}
// METHOD: generateId
// PARAMS: lenght in int
// RETURN: random string
// DESC : generateId :: Integer -> String
// only works on mondern browsers
function generateId(len)
{
var arr = new Uint8Array((len || 40) / 2);
(window.crypto || window.msCrypto).getRandomValues(arr);
return Array.from(arr, dec2hex).join('');
}
// METHOD: randomIdF()
// PARAMS: none
// RETURN: not true random string
// DESC : creates a pseudo random string of 10 characters
// after many runs it will create duplicates
function randomIdF()
{
return Math.random().toString(36).substring(2);
}
// METHOD: isObject
// PARAMS: possible object
// RETURN: true/false if it is an object or not
@@ -554,6 +586,8 @@ function phfo(tree)
// *** DOM MANAGEMENT FUNCTIONS
// BLOCK: html wrappers for quickly creating html data blocks
// NOTE : OLD FORMAT which misses multiple block set
// METHOD: html_options
// PARAMS: name/id, array for the options, selected item uid
// options_only [def false] if this is true, it will not print the select part
@@ -563,15 +597,40 @@ function phfo(tree)
// 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(name, data, selected = '', options_only = false, return_string = false, sort = '')
{
// wrapper to new call
return html_options_block(name, data, selected, false, options_only, return_string, sort);
}
// NOTE : USE THIS CALL, the above one is deprecated
// METHOD: html_options
// PARAMS: name/id, array for the options,
// 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 = 0, options_only = false, return_string = false, sort = '')
{
var content = [];
var element_select;
var select_options = {};
var element_option;
var data_list = []; // for sorted output
var value;
var options;
var option;
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);
element_select = cel('select', name, '', [], select_options);
// console.log('Call for %s, options: %s', name, options_only);
if (sort == 'keys') {
data_list = Object.keys(data).sort();
@@ -585,14 +644,18 @@ function html_options(name, data, selected = '', options_only = false, return_st
// 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

@@ -299,6 +299,38 @@ function getTimestamp()
return date.getTime();
}
// METHOD: dec2hex
// PARAMS: decimal string
// RETURN: string
// DESC : dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex(dec)
{
return ('0' + dec.toString(16)).substr(-2);
}
// METHOD: generateId
// PARAMS: lenght in int
// RETURN: random string
// DESC : generateId :: Integer -> String
// only works on mondern browsers
function generateId(len)
{
var arr = new Uint8Array((len || 40) / 2);
(window.crypto || window.msCrypto).getRandomValues(arr);
return Array.from(arr, dec2hex).join('');
}
// METHOD: randomIdF()
// PARAMS: none
// RETURN: not true random string
// DESC : creates a pseudo random string of 10 characters
// after many runs it will create duplicates
function randomIdF()
{
return Math.random().toString(36).substring(2);
}
// METHOD: isObject
// PARAMS: possible object
// RETURN: true/false if it is an object or not
@@ -632,6 +664,8 @@ function phfo(tree)
// *** DOM MANAGEMENT FUNCTIONS
// BLOCK: html wrappers for quickly creating html data blocks
// NOTE : OLD FORMAT which misses multiple block set
// METHOD: html_options
// PARAMS: name/id, array for the options, selected item uid
// options_only [def false] if this is true, it will not print the select part
@@ -641,15 +675,40 @@ function phfo(tree)
// 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(name, data, selected = '', options_only = false, return_string = false, sort = '')
{
// wrapper to new call
return html_options_block(name, data, selected, false, options_only, return_string, sort);
}
// NOTE : USE THIS CALL, the above one is deprecated
// METHOD: html_options
// PARAMS: name/id, array for the options,
// 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 = 0, options_only = false, return_string = false, sort = '')
{
var content = [];
var element_select;
var select_options = {};
var element_option;
var data_list = []; // for sorted output
var value;
var options;
var option;
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);
element_select = cel('select', name, '', [], select_options);
// console.log('Call for %s, options: %s', name, options_only);
if (sort == 'keys') {
data_list = Object.keys(data).sort();
@@ -663,14 +722,18 @@ function html_options(name, data, selected = '', options_only = false, return_st
// 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
@@ -1322,6 +1400,7 @@ class Basic
if (preg_match("/(d|h|m|s|ms)/", $timestring)) {
// pos for preg match read + multiply factor
$timegroups = array (2 => 86400, 4 => 3600, 6 => 60, 8 => 1);
$matches = array ();
// preg match: 0: full strsing
// 2, 4, 6, 8 are the to need values
preg_match("/^((\d+)d ?)?((\d+)h ?)?((\d+)m ?)?((\d+)s ?)?((\d+)ms)?$/", $timestring, $matches);
@@ -1453,12 +1532,14 @@ class Basic
// PARAMS: start date, end date
// RETURN: overall days, week days, weekend days as array 0...2 or named
// DESC : calculates the days between two dates
private function calcDaysInterval($start_date, $end_date, $return_named = false)
public static function calcDaysInterval($start_date, $end_date, $return_named = false)
{
// pos 0 all, pos 1 weekday, pos 2 weekend
$days = array ();
$start = new \DateTime($start_date);
$end = new \DateTime($end_date);
// so we include the last day too, we need to add +1 second in the time
$end->setTime(0, 0, 1);
$days[0] = $end->diff($start)->days;

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];