Compare commits

...

30 Commits

Author SHA1 Message Date
Clemens Schwaighofer
66b7e81463 Bug fix in DB\IO for EOM string build queries with returning
on EOM string build queries it was not checked that RETURNING could have
no space in front.

Fixed and updated test calls
2023-01-25 16:47:31 +09:00
Clemens Schwaighofer
cf58f86802 Remove not needed ?? '' in ACL\Login 2023-01-16 14:29:25 +09:00
Clemens Schwaighofer
ff644310cd Readme file update 2023-01-11 09:22:18 +09:00
Clemens Schwaighofer
58988b9c0f Rename edit schemes pages to schemas 2023-01-11 09:12:56 +09:00
Clemens Schwaighofer
fe75f1d724 Add missing table arrays and name fix schim
missed two table arrays as class EditVisibleGroup and EditAccess

also fix wrong name for EditSchemas (wrong: EditSchemes) with a shim
lookup.

edit_schemes.php file will stay the same for now.
2023-01-11 07:06:28 +09:00
Clemens Schwaighofer
0607cdc3be Add logger $log public entry in Form class
We need that for sub calls to debugger from TableArray loads
2023-01-10 18:19:20 +09:00
Clemens Schwaighofer
6cb14daf49 Move includes/table_arrays to class Output\Form\TableArrays
also remove the legacy edit_base.LEGACY.php file

All previous includes/table_arrays load via include are now moved to a
class system so we have all implemented in one folder and can easy update
and add unit tests to it.
2023-01-10 18:04:29 +09:00
Clemens Schwaighofer
330582f273 Add $this identifier to class in array_edit_users 2023-01-10 16:42:42 +09:00
Clemens Schwaighofer
b0293b52bd Fix edit_users load problem with removed globals
acl_admin/base_acl_leve

Added public access methods to read this when array_* files are included.
2023-01-10 16:01:02 +09:00
Clemens Schwaighofer
00591deb00 Add Check Color class
checks html/css color string for valid
eg, hex #, hex alpha #, rgb/rgba, hsl/hsla
2023-01-10 15:43:33 +09:00
Clemens Schwaighofer
737f70fac5 Fix phpdoc Exception name with missing \ 2023-01-10 14:40:16 +09:00
Clemens Schwaighofer
0328ccd2fe Convert\Colors fixes for from HSB/HSL Hue 360
If hue 360 is given, it is no longer an error but internally converted to 0
2023-01-10 14:07:01 +09:00
Clemens Schwaighofer
eba1e2885f Convert\Byte add exception
And exception is thrown for invalid flags
2023-01-10 14:06:09 +09:00
Clemens Schwaighofer
53813261fb Form\Generate update
- remove auto load _POST vars
- Update color settings to # leading 6/8 digit hex code
- remove any global variable calls/requests
- fix some isset/empty clean ups (isset + set = !empty)
- fix on delete of reference data that loaded data was not shown again
- fix on reference data save error that wrong data is still shown and not removed
2023-01-10 11:25:51 +09:00
Clemens Schwaighofer
df2ae66942 Bug fix for loading after new/save/delete 2023-01-06 15:16:01 +09:00
Clemens Schwaighofer
78e1d73cd9 Move code from edit_base.php to class file 2023-01-06 15:07:15 +09:00
Clemens Schwaighofer
620a5878c1 Update dotenv reader from Composer package 2023-01-06 10:51:12 +09:00
Clemens Schwaighofer
5a0b09a916 Add DB\IO get prepare cursor array entries 2023-01-05 17:26:26 +09:00
Clemens Schwaighofer
98c6033c75 mo to js script set exectueable 2023-01-05 15:31:35 +09:00
Clemens Schwaighofer
6dcebc9b67 mo to js shell script 2023-01-05 15:30:51 +09:00
Clemens Schwaighofer
c97520e186 Update flatpickr javascript lib 2023-01-05 15:14:08 +09:00
Clemens Schwaighofer
764ca1f098 fix Generate\Form test with missing session init 2023-01-05 11:32:39 +09:00
Clemens Schwaighofer
3d23e5b066 Composer update 2023-01-05 10:55:01 +09:00
Clemens Schwaighofer
90e418ba24 Smarty update to 4.3.0 2023-01-05 10:38:51 +09:00
Clemens Schwaighofer
b6a0937e0c autoloader update 2022-12-28 17:46:40 +09:00
Clemens Schwaighofer
b3f6f8ef18 Raname Progressbar.php to ProgressBar.php 2022-12-28 16:14:38 +09:00
Clemens Schwaighofer
d9d5400498 Add Test for get run times for unrun queryies 2022-12-28 11:31:39 +09:00
Clemens Schwaighofer
b1be681afb Bug fix in DB\IO for wrong array check
Did not use empty to check if query called hash entry exists
2022-12-28 11:26:56 +09:00
Clemens Schwaighofer
8ef309d479 PHP unit 8.2, cel builder br/input fix, doctype add, sync .user.ini
- do not sync .user.ini file in sync template
- add PHP 8.2 for test target phpunit
- cel/phfo builder update to not close br or img tags (besides input)
- psalm settings update
- add doctype to all base templates
2022-12-27 16:58:51 +09:00
Clemens Schwaighofer
6e59b63791 DB\IO phpdoc and phpstan fixes 2022-12-14 14:18:33 +09:00
607 changed files with 5270 additions and 24048 deletions

View File

@@ -26,6 +26,7 @@
use Phan\Config;
return [
// "target_php_version" => "8.2",
// turn color on (-C)
"color_issue_messages_if_supported" => true,
// If true, missing properties will be created when
@@ -95,7 +96,7 @@ return [
'www/vendor',
'www/tests',
'www/lib/Smarty',
'www/lib/smarty-4.1.0',
'www/lib/smarty-4.3.0',
'www/templates_c',
'www/log',
'www/tmp',
@@ -117,7 +118,9 @@ return [
'www/admin/qq_file_upload_front.php',
'www/admin/qq_file_upload_ajax.php',
// symlink ignore
'www/lib/smarty-4.1.0/libs/Smarty.class.php'
'www/lib/smarty-4.3.0/libs/Smarty.class.php',
// legacy edit base (until removal)
'www/includes/edit_base.LEGACY.php'
],
// what not to show as problem

169
4dev/bin/mo_to_js.sh Executable file
View File

@@ -0,0 +1,169 @@
#!/bin/bash
# read source mo files and writes target js files in object form
# check for ARG 1 is "mv"
# then move the files directly and don't do manual check (don't create temp files)
FILE_MOVE=0;
if [ "${1}" = "mv" ]; then
echo "*** Direct write ***";
FILE_MOVE=1;
fi;
target='';
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
# Assume script is in 4dev/bin
base_folder="${BASE_FOLDER}../../www/";
po_folder='../4dev/locale/'
mo_folder='includes/locale/';
target_folder='';
template_file_stump='##SUFFIX##translate-##LANGUAGE##.TMP.js';
# for output file names
source_list=(iw);
language_list=(en ja);
# set target names
if [ "${target}" == '' ]; then
echo "*** Non smarty ***";
TEXTDOMAINDIR=${base_folder}${mo_folder}.
# default is admin
TEXTDOMAIN=admin;
fi;
js_folder="layout/${TEXTDOMAIN}/javascript/";
error=0;
# this checks if the TEXTDOMAIN target actually exists
if [ ! -d "${base_folder}${js_folder}" ]; then
echo "Cannot find target javascript folder ${base_folder}${js_folder}";
error=1;
else
target_folder="${base_folder}${js_folder}";
fi;
if [ ${error} -eq 1 ]; then
exit;
fi;
# locale gettext po to mo translator master
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do
file=$(basename $file .po);
echo "Translate language ${file}";
locale=$(echo "${file}" | cut -d "-" -f 1);
domain=$(echo "${file}" | cut -d "-" -f 2);
if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then
mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/";
fi;
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}${po_folder}${locale}-${domain}.po;
done;
rx_msgid_empty="^msgid \"\"";
rx_msgid="^msgid \"";
rx_msgstr="^msgstr \""
# quick copy string at the end
quick_copy='';
for language in ${language_list[*]}; do
# I don't know which one must be set, but I think at least LANGUAGE
case ${language} in
ja)
LANG=ja_JP.UTF-8;
ENCODING=UTF-8;
LANGUAGE=ja;
;;
en)
# was en_JP.UTF-8
LANG=en_US.UTF-8;
ENCODING=UTF-8;
LANGUAGE=en;
;;
esac;
# write only one for language and then symlink files
template_file=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##//" | sed -e "s/##LANGUAGE##/${LANG}/");
original_file=$(echo ${template_file} | sed -e 's/\.TMP//g');
if [ "${FILE_MOVE}" -eq 0 ]; then
file=${target_folder}${template_file};
else
file=${target_folder}${original_file};
fi;
echo "===> Write translation file ${file}";
echo ". = normal, : = escape, x = skip";
# init line [aka don't touch this file]
echo "// AUTO FILL, changes will be overwritten" > $file;
echo "// source: ${suffix}, language: ${language}" >> $file;
echo "// Translation strings in the format" >> $file;
echo "// \"Original\":\"Translated\""$'\n' >> $file;
echo "var i18n = {" >> $file;
# translations stuff
# read the po file
pos=0; # do we add a , for the next line
cat "${base_folder}${po_folder}${language}-${TEXTDOMAIN}.po" |
while read str; do
# echo "S: ${str}";
# skip empty
if [[ "${str}" =~ ${rx_msgid_empty} ]]; then
# skip on empty
echo -n "x";
# msgid is left, msgstr is right
elif [[ "${str}" =~ ${rx_msgid} ]]; then
echo -n ".";
# open left side
# TODO: how to handle multi line strings: or don't use them
# extract from between ""
str_source=$(echo "${str}" | sed -e "s/^msgid \"//" | sed -e "s/\"$//");
# close right side, if not last add ,
if [ "${pos}" -eq 1 ]; then
echo -n "," >> $file;
fi;
# all " inside string need to be escaped
str_source=$(echo "${str_source}" | sed -e 's/"/\\"/g');
# fix with proper layout
echo -n "\"$str_source\":\"$(TEXTDOMAINDIR=${TEXTDOMAINDIR} LANGUAGE=${language} LANG=${LANG} gettext ${TEXTDOMAIN} "${str_source}")\"" >> $file;
pos=1;
elif [[ "${str}" =~ ${rx_msgstr} ]]; then
# open right side (ignore)
echo -n "";
else
# general ignore (anything between or comments)
echo -n "";
fi;
done;
echo "" >> $file;
echo "};" >> $file;
echo " [DONE]";
# on no move
if [ "${FILE_MOVE}" -eq 0 ]; then
echo "===> Confirm all changes in ${file} and then move data to original";
echo "";
quick_copy=${quick_copy}"mv ${template_file} ${original_file}"$'\n';
fi;
# symlink to master file
for suffix in ${source_list[*]}; do
# symlink with full lang name
symlink_file[0]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANG}/" | sed -e 's/\.TMP//g');
# create second one with lang (no country) + encoding
symlink_file[1]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANGUAGE}\.${ENCODING}/" | sed -e 's/\.TMP//g');
for template_file in ${symlink_file[@]}; do
# if this is not symlink, create them
if [ ! -h "${template_file}" ]; then
echo "Create symlink: ${template_file}";
# symlik to original
cd "${target_folder}";
ln -sf "${original_file}" "${template_file}";
cd - >/dev/null;
fi;
done;
done;
done;
if [ "${FILE_MOVE}" -eq 0 ]; then
echo "";
echo "-- IN FOLDER: ${target_folder}";
echo "-- START: copy lines below to copy created over original --";
echo "${quick_copy}";
echo "-- END ----------------------------------------------------";
fi;
# __END__

View File

@@ -3,7 +3,7 @@ base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
# --testdox
# call with "t" to give verbose testdox output
# SUPPORTED: https://www.php.net/supported-versions.php
# call with 7.3, 7.4, 8.0, 8.1 to force a certain php version
# call with 7.4, 8.0, 8.1 to force a certain php version
opt_testdox="";
if [ "${1}" = "t" ] || [ "${2}" = "t" ]; then
@@ -16,6 +16,7 @@ if [ ! -z "${1}" ]; then
"7.4") php_bin="/usr/bin/php7.4 "; ;;
"8.0") php_bin="/usr/bin/php8.0 "; ;;
"8.1") php_bin="/usr/bin/php8.1 "; ;;
"8.2") php_bin="/usr/bin/php8.2 "; ;;
*) echo "Not support PHP: ${1}"; exit; ;;
esac;
fi;
@@ -25,6 +26,7 @@ if [ ! -z "${2}" ] && [ -z "${php_bin}" ]; then
"7.4") php_bin="/usr/bin/php7.4 "; ;;
"8.0") php_bin="/usr/bin/php8.0 "; ;;
"8.1") php_bin="/usr/bin/php8.1 "; ;;
"8.2") php_bin="/usr/bin/php8.2 "; ;;
*) echo "Not support PHP: ${1}"; exit; ;;
esac;
fi;

View File

@@ -18,6 +18,7 @@ rm -f $tmpf_web;
echo ".*.swp" >> $tmpf_web;
echo "._*" >> $tmpf_web;
echo ".DS_Store" >> $tmpf_web;
echo ".user.ini" >> $tmpf_web;
echo ".svn" >> $tmpf_web;
echo ".svnignore" >> $tmpf_web;
echo ".git" >> $tmpf_web;

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
/**
* Test class for Admin\EditPage
* @coversDefaultClass \CoreLibs\Admin\EditPage
* @testdox \CoreLibs\Admin\EditPage method tests
*/
final class CoreLibsAdminEditPageTest extends TestCase
{
/**
* Undocumented function
*
* @return void
*/
protected function setUp(): void
{
if (!extension_loaded('pgsql')) {
$this->markTestSkipped(
'The PgSQL extension is not available.'
);
}
}
/**
* Undocumented function
*
* @testdox Admin\EditPage Class tests
*
* @return void
*/
public function testAdminEditPage()
{
/* $this->assertTrue(true, 'ACL Login Tests not implemented');
$this->markTestIncomplete(
'ACL\Login Tests have not yet been implemented'
); */
$this->markTestSkipped('No implementation for Admin\EditPage at the moment');
}
}
// __END__

View File

@@ -0,0 +1,329 @@
<?php
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
/**
* Test class for Check\Colors
* @coversDefaultClass \CoreLibs\Check\Colors
* @testdox \CoreLibs\Check\Colors method tests
*/
final class CoreLibsCheckColorsTest extends TestCase
{
public function validateColorProvider(): array
{
/*
0: input color string
1: flag (or flags to set)
2: expected result (bool)
*/
return [
// * hex
'valid hex rgb, flag ALL (default)' => [
'#ab12cd',
null,
true,
],
'valid hex rgb, flag ALL' => [
'#ab12cd',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid hex rgb, flag HEX_RGB' => [
'#ab12cd',
\CoreLibs\Check\Colors::HEX_RGB,
true,
],
'valid hex rgb, wrong flag' => [
'#ab12cd',
\CoreLibs\Check\Colors::RGB,
false,
],
// error
'invalid hex rgb A' => [
'#ab12zz',
null,
false,
],
'invalid hex rgb B' => [
'#ZyQfo',
null,
false,
],
// other valid hex checks
'valid hex rgb, alt A' => [
'#AB12cd',
null,
true,
],
// * hax alpha
'valid hex rgb alpha, flag ALL (default)' => [
'#ab12cd12',
null,
true,
],
'valid hex rgb alpha, flag ALL' => [
'#ab12cd12',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid hex rgb alpha, flag HEX_RGBA' => [
'#ab12cd12',
\CoreLibs\Check\Colors::HEX_RGBA,
true,
],
'valid hex rgb alpha, wrong flag' => [
'#ab12cd12',
\CoreLibs\Check\Colors::RGB,
false,
],
// error
'invalid hex rgb alpha A' => [
'#ab12dd1',
null,
false,
],
'invalid hex rgb alpha B' => [
'#ab12ddzz',
null,
false,
],
'valid hex rgb alpha, alt A' => [
'#ab12cdEE',
null,
true,
],
// * rgb
'valid rgb, flag ALL (default)' => [
'rgb(255, 10, 20)',
null,
true,
],
'valid rgb, flag ALL' => [
'rgb(255, 10, 20)',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid rgb, flag RGB' => [
'rgb(255, 10, 20)',
\CoreLibs\Check\Colors::RGB,
true,
],
'valid rgb, wrong flag' => [
'rgb(255, 10, 20)',
\CoreLibs\Check\Colors::HEX_RGB,
false,
],
// error
'invalid rgb A' => [
'rgb(356, 10, 20)',
null,
false,
],
// other valid rgb conbinations
'valid rgb, alt A (percent)' => [
'rgb(100%, 10%, 20%)',
null,
true,
],
// TODO check all % and non percent combinations
'valid rgb, alt B (percent, mix)' => [
'rgb(100%, 10, 40)',
null,
true,
],
// * rgb alpha
'valid rgba, flag ALL (default)' => [
'rgba(255, 10, 20, 0.5)',
null,
true,
],
'valid rgba, flag ALL' => [
'rgba(255, 10, 20, 0.5)',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid rgba, flag RGB' => [
'rgba(255, 10, 20, 0.5)',
\CoreLibs\Check\Colors::RGBA,
true,
],
'valid rgba, wrong flag' => [
'rgba(255, 10, 20, 0.5)',
\CoreLibs\Check\Colors::HEX_RGB,
false,
],
// error
'invalid rgba A' => [
'rgba(356, 10, 20, 0.5)',
null,
false,
],
// other valid rgba combinations
'valid rgba, alt A (percent)' => [
'rgba(100%, 10%, 20%, 0.5)',
null,
true,
],
// TODO check all % and non percent combinations
'valid rgba, alt B (percent, mix)' => [
'rgba(100%, 10, 40, 0.5)',
null,
true,
],
// TODO check all % and non percent combinations with percent transparent
'valid rgba, alt C (percent transparent)' => [
'rgba(100%, 10%, 20%, 50%)',
null,
true,
],
/*
// hsl
'hsl(100, 50%, 60%)',
'hsl(100, 50.5%, 60.5%)',
'hsla(100, 50%, 60%)',
'hsla(100, 50.5%, 60.5%)',
'hsla(100, 50%, 60%, 0.5)',
'hsla(100, 50.5%, 60.5%, 0.5)',
'hsla(100, 50%, 60%, 50%)',
'hsla(100, 50.5%, 60.5%, 50%)',
*/
// * hsl
'valid hsl, flag ALL (default)' => [
'hsl(100, 50%, 60%)',
null,
true,
],
'valid hsl, flag ALL' => [
'hsl(100, 50%, 60%)',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid hsl, flag RGB' => [
'hsl(100, 50%, 60%)',
\CoreLibs\Check\Colors::HSL,
true,
],
'valid hsl, wrong flag' => [
'hsl(100, 50%, 60%)',
\CoreLibs\Check\Colors::HEX_RGB,
false,
],
'invalid hsl A' => [
'hsl(500, 50%, 60%)',
null,
false,
],
'valid hsl, alt A' => [
'hsl(100, 50.5%, 60.5%)',
null,
true,
],
// * hsl alpha
'valid hsla, flag ALL (default)' => [
'hsla(100, 50%, 60%, 0.5)',
null,
true,
],
'valid hsla, flag ALL' => [
'hsla(100, 50%, 60%, 0.5)',
\CoreLibs\Check\Colors::ALL,
true,
],
'valid hsla, flag RGB' => [
'hsla(100, 50%, 60%, 0.5)',
\CoreLibs\Check\Colors::HSLA,
true,
],
'valid hsla, wrong flag' => [
'hsla(100, 50%, 60%, 0.5)',
\CoreLibs\Check\Colors::HEX_RGB,
false,
],
'invalid hsla A' => [
'hsla(500, 50%, 60%, 0.5)',
null,
false,
],
'valid hsla, alt A (percent alpha' => [
'hsla(100, 50%, 60%, 50%)',
null,
true,
],
'valid hsla, alt A (percent alpha' => [
'hsla(100, 50.5%, 60.5%, 50%)',
null,
true,
],
// * combined flag checks
'valid rgb, flag RGB|RGBA' => [
'rgb(100%, 10%, 20%)',
\CoreLibs\Check\Colors::RGB | \CoreLibs\Check\Colors::RGBA,
true,
],
// TODO other combined flag checks all combinations
// * invalid string
'invalid string A' => [
'invalid string',
null,
false,
],
'invalid string B' => [
'(hsla(100, 100, 100))',
null,
false,
],
'invalid string C' => [
'hsla(100, 100, 100',
null,
false,
],
];
}
/**
* Undocumented function
*
* @covers ::validateColor
* @dataProvider validateColorProvider
* @testdox validateColor $input with flags $flags be $expected [$_dataName]
*
* @param string $input
* @param int|null $flags
* @param bool $expected
* @return void
*/
public function testValidateColor(string $input, ?int $flags, bool $expected)
{
if ($flags === null) {
$result = \CoreLibs\Check\Colors::validateColor($input);
} else {
$result = \CoreLibs\Check\Colors::validateColor($input, $flags);
}
$this->assertEquals(
$expected,
$result
);
}
/**
* Undocumented function
*
* @covers ::validateColor
* @testWith [99]
* @testdox Check Exception throw for $flag
*
* @param int $flag
* @return void
*/
public function testValidateColorException(int $flag): void
{
$this->expectException(\Exception::class);
\CoreLibs\Check\Colors::validateColor('#ffffff', $flag);
}
}
// __END__

View File

@@ -240,6 +240,41 @@ final class CoreLibsConvertByteTest extends TestCase
\CoreLibs\Convert\Byte::stringByteFormat($input, \CoreLibs\Convert\Byte::BYTE_FORMAT_SI)
);
}
/**
* Exceptions tests
*
* @covers ::humanReadableByteFormat
* @testWith [99]
* @testdox Test exception for humanReadableByteFormat with flag $flag
*
* @param int $flag
* @return void
*/
public function testHumanReadableByteFormatException(int $flag): void
{
$this->expectException(\Exception::class);
\CoreLibs\Convert\Byte::humanReadableByteFormat(12, $flag);
}
/**
* Exceptions tests
* can only be 4, try 1,2 and over
*
* @covers ::stringByteFormat
* @testWith [1]
* [2]
* [99]
* @testdox Test exception for stringByteFormat with flag $flag
*
* @param int $flag
* @return void
*/
public function testStringByteFormatException(int $flag): void
{
$this->expectException(\Exception::class);
\CoreLibs\Convert\Byte::stringByteFormat(12, $flag);
}
}
// __END__

View File

@@ -122,6 +122,8 @@ final class CoreLibsConvertColorsTest extends TestCase
*/
public function rgb2hslAndhsbList(): array
{
// if hsb_from or hsl_from is set, this will be used in hsb/hsl convert
// hsb_rgb is used for adjusted rgb valus due to round error to in
return [
'valid gray' => [
'rgb' => [12, 12, 12],
@@ -137,6 +139,16 @@ final class CoreLibsConvertColorsTest extends TestCase
'hsl' => [211.6, 90.5, 41.2],
'valid' => true,
],
// hsg/hsl with 360 which is seen as 0
'valid color hue 360' => [
'rgb' => [200, 10, 10],
'hsb' => [0, 95, 78.0],
'hsb_from' => [360, 95, 78.0],
'hsb_rgb' => [199, 10, 10], // should be rgb, but rounding error
'hsl' => [0.0, 90.5, 41.2],
'hsl_from' => [360.0, 90.5, 41.2],
'valid' => true,
],
// invalid values
'invalid color' => [
'rgb' => [-12, 300, 12],
@@ -176,9 +188,9 @@ final class CoreLibsConvertColorsTest extends TestCase
$list = [];
foreach ($this->rgb2hslAndhsbList() as $name => $values) {
$list[$name . ', hsb to rgb'] = [
0 => $values['hsb'][0],
1 => $values['hsb'][1],
2 => $values['hsb'][2],
0 => $values['hsb_from'][0] ?? $values['hsb'][0],
1 => $values['hsb_from'][1] ?? $values['hsb'][1],
2 => $values['hsb_from'][2] ?? $values['hsb'][2],
3 => $values['valid'] ? $values['hsb_rgb'] : false
];
}
@@ -214,9 +226,9 @@ final class CoreLibsConvertColorsTest extends TestCase
$list = [];
foreach ($this->rgb2hslAndhsbList() as $name => $values) {
$list[$name . ', hsl to rgb'] = [
0 => $values['hsl'][0],
1 => $values['hsl'][1],
2 => $values['hsl'][2],
0 => $values['hsl_from'][0] ?? $values['hsl'][0],
1 => $values['hsl_from'][1] ?? $values['hsl'][1],
2 => $values['hsl_from'][2] ?? $values['hsl'][2],
3 => $values['valid'] ? $values['rgb'] : false
];
}
@@ -382,6 +394,27 @@ final class CoreLibsConvertColorsTest extends TestCase
\CoreLibs\Convert\Colors::hsl2rgb($input_h, $input_s, $input_l)
);
}
/**
* edge case check hsl/hsb and hue 360 (= 0)
*
* @covers ::hsl2rgb
* @covers ::hsb2rgb
* @testdox hsl2rgb/hsb2rgb hue 360 valid check
*
* @return void
*/
public function testHslHsb360hue(): void
{
$this->assertNotFalse(
\CoreLibs\Convert\Colors::hsl2rgb(360.0, 90.5, 41.2),
'HSL to RGB with 360 hue'
);
$this->assertNotFalse(
\CoreLibs\Convert\Colors::hsb2rgb(360, 95, 78.0),
'HSB to RGB with 360 hue'
);
}
}
// __END__

View File

@@ -155,37 +155,57 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbExec("DROP TABLE table_without_primary_key");
$db->dbExec("DROP TABLE test_meta");
}
$base_table = "uid VARCHAR, " // uid is for internal reference tests
. "row_int INT, "
. "row_numeric NUMERIC, "
. "row_varchar VARCHAR, "
. "row_varchar_literal VARCHAR, "
. "row_json JSON, "
. "row_jsonb JSONB, "
. "row_bytea BYTEA, "
. "row_timestamp TIMESTAMP WITHOUT TIME ZONE, "
. "row_date DATE, "
. "row_interval INTERVAL, "
. "row_array_int INT ARRAY, "
. "row_array_varchar VARCHAR ARRAY"
. ") WITHOUT OIDS";
// uid is for internal reference tests
$base_table = <<<EOM
uid VARCHAR,
row_int INT,
row_numeric NUMERIC,
row_varchar VARCHAR,
row_varchar_literal VARCHAR,
row_json JSON,
row_jsonb JSONB,
row_bytea BYTEA,
row_timestamp TIMESTAMP WITHOUT TIME ZONE,
row_date DATE,
row_interval INTERVAL,
row_array_int INT ARRAY,
row_array_varchar VARCHAR ARRAY
)
WITHOUT OIDS
EOM;
// create the tables
$db->dbExec(
"CREATE TABLE table_with_primary_key ("
// primary key name is table + '_id'
<<<EOM
CREATE TABLE table_with_primary_key (
table_with_primary_key_id SERIAL PRIMARY KEY,
$base_table
EOM
/* "CREATE TABLE table_with_primary_key ("
// primary key name is table + '_id'
. "table_with_primary_key_id SERIAL PRIMARY KEY, "
. $base_table
. $base_table */
);
$db->dbExec(
"CREATE TABLE table_without_primary_key ("
. $base_table
<<<EOM
CREATE TABLE table_without_primary_key (
$base_table
EOM
/* "CREATE TABLE table_without_primary_key ("
. $base_table */
);
// create simple table for meta test
$db->dbExec(
"CREATE TABLE test_meta ("
<<<EOM
CREATE TABLE test_meta (
row_1 VARCHAR,
row_2 INT
) WITHOUT OIDS
EOM
/* "CREATE TABLE test_meta ("
. "row_1 VARCHAR, "
. "row_2 INT"
. ") WITHOUT OIDS"
. ") WITHOUT OIDS" */
);
// set some test schema
$db->dbExec("CREATE SCHEMA IF NOT EXISTS testschema");
@@ -1576,6 +1596,13 @@ final class CoreLibsDBIOTest extends TestCase
// clear any current query
// $db->dbResetQuery();
// assert never called query is 0
$this->assertEquals(
0,
$db->dbGetQueryCalled($query),
'Assert never called query is null'
);
// if expected result is not a bool
// for PHP 8.1 or higher it has to be an object
// for anything before PHP 8.1 this has to be a resource
@@ -2763,7 +2790,7 @@ final class CoreLibsDBIOTest extends TestCase
}
// - prepared query execute
// dbPrepare, dbExecute, dbFetchArray
// dbPrepare, dbExecute, dbFetchArray, dbGetPrepareCursorValue
/**
* Undocumented function
@@ -2788,6 +2815,7 @@ final class CoreLibsDBIOTest extends TestCase
// 11: read query (if insert/update)
// 11: execute data to check (array)
// 12: insert data
// 13: prepated cursor array data match values
return [
// insert
'prepare query insert' => [
@@ -2811,6 +2839,14 @@ final class CoreLibsDBIOTest extends TestCase
],
// insert data (for select)
'',
// get prepared data
[
'pk_name' => 'table_with_primary_key_id',
'count' => 2,
'query' => 'INSERT INTO table_with_primary_key (row_int, uid) '
. 'VALUES ($1, $2) RETURNING table_with_primary_key_id',
'returning_id' => true,
],
],
// update
'prepare query update' => [
@@ -2837,6 +2873,14 @@ final class CoreLibsDBIOTest extends TestCase
//
"INSERT INTO table_with_primary_key (row_int, uid) VALUES "
. "(111, 'TEST A')",
//
[
'pk_name' => '',
'count' => 3,
'query' => 'UPDATE table_with_primary_key SET row_int = $1, '
. 'row_varchar = $2 WHERE uid = $3',
'returning_id' => false,
],
],
// select
'prepare select query' => [
@@ -2858,7 +2902,14 @@ final class CoreLibsDBIOTest extends TestCase
],
],
//
$insert_query
$insert_query,
//
[
'pk_name' => '',
'count' => 1,
'query' => 'SELECT row_int, uid FROM table_with_primary_key WHERE uid = $1',
'returning_id' => false,
],
],
// any query but with no parameters
'prepare select query no parameter' => [
@@ -2883,7 +2934,14 @@ final class CoreLibsDBIOTest extends TestCase
],
],
//
$insert_query
$insert_query,
//
[
'pk_name' => '',
'count' => 0,
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'returning_id' => false,
],
],
// no statement name (25)
'empty statement' => [
@@ -2900,6 +2958,13 @@ final class CoreLibsDBIOTest extends TestCase
[],
//
'',
//
[
'pk_name' => '',
'count' => 0,
'query' => '',
'returning_id' => false,
],
],
// no query (prepare 11)
// no prepared cursor found with statement name (execute 24)
@@ -2917,6 +2982,13 @@ final class CoreLibsDBIOTest extends TestCase
[],
//
'',
//
[
'pk_name' => '',
'count' => 0,
'query' => '',
'returning_id' => false,
],
],
// no db connection (prepare/execute 16)
// TODO no db connection test
@@ -2937,8 +3009,15 @@ final class CoreLibsDBIOTest extends TestCase
// no query but data for data only compare
'',
[],
//,
$insert_query
//
$insert_query,
//
[
'pk_name' => '',
'count' => 0,
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'returning_id' => false,
],
],
// insert wrong data count compared to needed (execute 23)
'wrong parmeter count' => [
@@ -2955,7 +3034,15 @@ final class CoreLibsDBIOTest extends TestCase
'',
[],
//
''
'',
//
[
'pk_name' => 'table_with_primary_key_id',
'count' => 2,
'query' => 'INSERT INTO table_with_primary_key (row_int, uid) VALUES '
. '($1, $2) RETURNING table_with_primary_key_id',
'returning_id' => true,
],
],
// execute does not return a result (22)
// TODO execute does not return a result
@@ -2968,6 +3055,7 @@ final class CoreLibsDBIOTest extends TestCase
* @covers ::dbPrepare
* @covers ::dbExecute
* @covers ::dbFetchArray
* @covers ::dbGetPrepareCursorValue
* @dataProvider preparedProvider
* @testdox prepared query $stm_name with $expected_prepare (warning $warning_prepare/error $error_prepare) and $expected_execute (warning $warning_execute/error $error_execute) [$_dataName]
*
@@ -2984,6 +3072,7 @@ final class CoreLibsDBIOTest extends TestCase
* @param string $expected_data_query
* @param array $expected_data
* @param string $insert_data
* @param array $prepare_cursor
* @return void
*/
public function testDbPrepared(
@@ -2999,7 +3088,8 @@ final class CoreLibsDBIOTest extends TestCase
string $error_execute,
string $expected_data_query,
array $expected_data,
string $insert_data
string $insert_data,
array $prepare_cursor,
): void {
// self::$log->setLogLevelAll('debug', true);
// self::$log->setLogLevelAll('print', true);
@@ -3109,6 +3199,15 @@ final class CoreLibsDBIOTest extends TestCase
);
}
// check dbGetPrepareCursorValue
foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
$this->assertEquals(
$prepare_cursor[$key],
$db->dbGetPrepareCursorValue($stm_name, $key),
'Prepared cursor: ' . $key . ': failed assertion'
);
}
// reset all data
$db->dbExec("TRUNCATE table_with_primary_key");
$db->dbExec("TRUNCATE table_without_primary_key");
@@ -3116,6 +3215,90 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbClose();
}
// dedicated error checks for prepare cursor return
/**
* Undocumented function
*
* @return array
*/
public function preparedProviderValue(): array
{
// 1: query (can be empty for do not set)
// 2: stm name
// 3: key
// 4: expected error return
return [
'no error' => [
"SELECT row_int, uid FROM table_with_primary_key",
'read',
'pk_name',
''
],
'statement name empty' => [
'',
'',
'',
'101',
],
'key empty' => [
'',
'read',
'',
'102',
],
'key invalid' => [
'',
'read',
'invalid',
'102',
],
'statement name not found' => [
'',
'invalid',
'pk_name',
'103',
],
];
}
/**
* test return prepare cursor errors
*
* @covers ::dbGetPrepareCursorValue
* @dataProvider preparedProviderValue
* @testdox prepared query $stm_name with $key expect error id $error_id [$_dataName]
*
* @param string $query
* @param string $stm_name
* @param string $key
* @param string $error_id
* @return void
*/
public function testDbGetPrepareCursorValue(
string $query,
string $stm_name,
string $key,
$error_id
): void {
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
);
if (!empty($query)) {
$db->dbPrepare($stm_name, $query);
$db->dbExecute($stm_name);
}
$db->dbGetPrepareCursorValue($stm_name, $key);
// match check error
$last_error = $db->dbGetLastError();
$this->assertEquals(
$error_id,
$last_error,
'get prepare cursor value error check'
);
}
// - schema set/get tests
// dbGetSchema, dbSetSchema
@@ -3730,6 +3913,38 @@ final class CoreLibsDBIOTest extends TestCase
]
]
],
// same but as EOM
'single insert (PK), EOM string' => [
<<<EOM
INSERT INTO table_with_primary_key (
row_varchar, row_varchar_literal, row_int, row_date
) VALUES (
'Text', 'Other', 123, '2022-03-01'
)
RETURNING row_varchar, row_varchar_literal, row_int, row_date
EOM,
null,
null,
null,
[
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
// 'table_with_primary_key_id' => "/^\d+$/",
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
],
[
0 => [
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
// 'table_with_primary_key_id' => "/^\d+$/",
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
]
]
],
// double insert (PK)
'dobule insert (PK)' => [
"INSERT INTO table_with_primary_key "
@@ -3747,14 +3962,14 @@ final class CoreLibsDBIOTest extends TestCase
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
],
1 => [
'row_varchar' => 'Foxtrott',
'row_varchar_literal' => 'Tango',
'row_int' => 789,
'row_date' => '1982-10-15',
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
'table_with_primary_key_id' => $table_with_primary_key_id + 4,
],
],
[
@@ -3763,14 +3978,14 @@ final class CoreLibsDBIOTest extends TestCase
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
],
1 => [
'row_varchar' => 'Foxtrott',
'row_varchar_literal' => 'Tango',
'row_int' => 789,
'row_date' => '1982-10-15',
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
'table_with_primary_key_id' => $table_with_primary_key_id + 4,
],
]
],
@@ -3798,7 +4013,35 @@ final class CoreLibsDBIOTest extends TestCase
'row_date' => '2022-03-01',
]
]
]
],
// same as above but as EOM string
'single insert (No PK), EOM string' => [
<<<EOM
INSERT INTO table_without_primary_key (
row_varchar, row_varchar_literal, row_int, row_date
) VALUES (
'Text', 'Other', 123, '2022-03-01'
)
RETURNING row_varchar, row_varchar_literal, row_int, row_date
EOM,
null,
null,
null,
[
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
],
[
0 => [
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
]
]
],
];
}
@@ -3845,11 +4088,13 @@ final class CoreLibsDBIOTest extends TestCase
$this->assertEquals(
$expected_ret_ext,
$returning_ext
$returning_ext,
'Returning extended failed'
);
$this->assertEquals(
$expected_ret_arr,
$returning_arr
$returning_arr,
'Returning Array failed'
);
// print "EXT: " . print_r($returning_ext, true) . "\n";

View File

@@ -0,0 +1,20 @@
# Files to be changed
Change: Update edit_page and template/css
Date: 2023/1/6
## Detail
* add stripes to sub table entries (edit.css)
* fix cellspacing and cellpadding in sub tables (edit_element.tpl)
* doctype added (edit_order.tpl)
* code clean up in edit base, move to class system (edit_base.php)
## File List
```sh
includes/templates/admin/edit_elements.tpl
includes/templates/admin/edit_order.tpl
includes/edit_base.php
layout/admin/css/edit.css
```

View File

@@ -0,0 +1,25 @@
-- Fixes for column types
-- edit group
ALTER TABLE edit_group ALTER name TYPE VARCHAR;
-- edit language
ALTER TABLE edit_language ALTER short_name TYPE VARCHAR;
ALTER TABLE edit_language ALTER long_name TYPE VARCHAR;
ALTER TABLE edit_language ALTER iso_name TYPE VARCHAR;
-- edit menu group
ALTER TABLE edit_menu_group ALTER name TYPE VARCHAR;
ALTER TABLE edit_menu_group ALTER flag TYPE VARCHAR;
-- edit page
ALTER TABLE edit_page ALTER filename TYPE VARCHAR;
ALTER TABLE edit_page ALTER name TYPE VARCHAR;
-- edit query string
ALTER TABLE edit_query_string ALTER name TYPE VARCHAR;
ALTER TABLE edit_query_string ALTER value TYPE VARCHAR;
-- edit scheme
ALTER TABLE edit_scheme ALTER name TYPE VARCHAR;
ALTER TABLE edit_scheme ALTER header_color TYPE VARCHAR;
ALTER TABLE edit_scheme ALTER css_file TYPE VARCHAR;
ALTER TABLE edit_scheme ALTER template TYPE VARCHAR;
-- edit visible group
ALTER TABLE edit_visible_group ALTER name TYPE VARCHAR;
ALTER TABLE edit_visible_group ALTER flag TYPE VARCHAR;

View File

@@ -0,0 +1,7 @@
-- Fix for edit_schemes.php DB settings
-- will not change file name only visual name
UPDATE edit_page SET name = 'Edit Schemas' WHERE filename = 'edit_schemes.php';
-- will change BOTH, must have file name renamed too
UPDATE edit_page SET name = 'Edit Schemas', filename = 'edit_schemas.php' WHERE filename = 'edit_schemes.php';

View File

@@ -2,19 +2,20 @@
## Code Standard
* Uses PSR-12
* tab indent instead of 4 spaces indent
* Warning at 120 character length, error at 240 character length
* Uses PSR-12
* tab indent instead of 4 spaces indent
* Warning at 120 character length, error at 240 character length
## General information
Base PHP class files to setup any project
* login
* database wrapper
* basic helper class for debugging and other features
* admin/frontend split
* domain controlled database/settings split
* dynamic layout groups
* login
* database wrapper
* basic helper class for debugging and other features
* admin/frontend split
* domain controlled database/settings split
* dynamic layout groups
## NOTE
@@ -50,7 +51,6 @@ pslam is setup but not configured
With phpunit (`4dev/checking/phpunit.sh`)
`phpunit -c $phpunit.xml 4dev/tests/`
## Other Notes
### Session used
@@ -58,29 +58,38 @@ With phpunit (`4dev/checking/phpunit.sh`)
The following classes use _SESSION
The main one is ACL\Login, this class will fail without a session started
* \CoreLibs\ACL\Login
* \CoreLibs\Admin\Backend
* \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\Form\Token
* \CoreLibs\Template\SmartyExtend
* \CoreLibs\ACL\Login
* \CoreLibs\Admin\Backend
* \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\Form\Token
* \CoreLibs\Template\SmartyExtend
### Class extends
The following classes extend these classes
* \CoreLibs\ACL\Login extends \CoreLibs\DB\IO
* \CoreLibs\Admin\Backend extends \CoreLibs\DB\IO
* \CoreLibs\DB\Extended\ArrayIO extends \CoreLibs\DB\IO
* \CoreLibs\Output\Form\Generate extends \CoreLibs\DB\Extended\ArrayIO
* \CoreLibs\Template\SmartyExtend extends SmartyBC
* \CoreLibs\ACL\Login extends \CoreLibs\DB\IO
* \CoreLibs\Admin\Backend extends \CoreLibs\DB\IO
* \CoreLibs\DB\Extended\ArrayIO extends \CoreLibs\DB\IO
* \CoreLibs\Output\Form\Generate extends \CoreLibs\DB\Extended\ArrayIO
* \CoreLibs\Template\SmartyExtend extends SmartyBC
### Class used
The following classes use the following classes
* \CoreLibs\ACL\Login uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\DB\IO uses \CoreLibs\Debug\Logger, \CoreLibs\DB\SQL\PgSQL
* \CoreLibs\Admin\Backend uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\Output\Form\Generate uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\ACL\Login uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\DB\IO uses \CoreLibs\Debug\Logging, \CoreLibs\DB\SQL\PgSQL
* \CoreLibs\Admin\Backend uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\Output\Form\Generate uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\Template\SmartyExtend uses \CoreLibs\Language\L10n
* \CoreLibs\Language\L10n uses FileReader, GetTextReader
* \CoreLibs\Admin\EditBase uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
### Class internal load
Loads classes internal (not passed in, not extend)
* \CoreLibs\Admin\EditBase loads \CoreLibs\Template\SmartyExtend, \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\From\Generate loads \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n if not passed on
* \CoreLibs\Output\From\Generate loads \CoreLibs\Output\From\TableArrays

View File

@@ -36,6 +36,7 @@ parameters:
# deprecated files
- www/includes/admin_set_paths.php # ignore the admin include stuff
- www/includes/admin_smarty.php # ignore the admin include stuff
- www/includes/edit_base.LEGACY.php # old style
# folders with data no check needed
- www/templates_c
- www/cache

View File

@@ -0,0 +1,123 @@
<?php // phpcs:ignore warning
/**
* @phan-file-suppress PhanTypeSuspiciousStringExpression
*/
declare(strict_types=1);
$DEBUG_ALL_OVERRIDE = 0; // set to 1 to debug on live/remote server locations
$DEBUG_ALL = 1;
$PRINT_ALL = 1;
$DB_DEBUG = 1;
if ($DEBUG_ALL) {
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
}
ob_start();
// basic class test file
define('USE_DATABASE', false);
// sample config
require 'config.php';
// define log file id
$LOG_FILE_ID = 'classTest-check-colors';
ob_end_flush();
use CoreLibs\Check\Colors;
// use CoreLibs\Debug\Support as DgS;
$log = new CoreLibs\Debug\Logging([
'log_folder' => BASE . LOG,
'file_id' => $LOG_FILE_ID,
// add file date
'print_file_date' => true,
// set debug and print flags
'debug_all' => $DEBUG_ALL ?? false,
'echo_all' => $ECHO_ALL ?? false,
'print_all' => $PRINT_ALL ?? false,
]);
$PAGE_NAME = 'TEST CLASS: CHECK COLORS';
print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
print "<body>";
print '<div><a href="class_test.php">Class Test Master</a></div>';
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
// list of colors to check
$css_colors = [
// base hex
'#ab12cd',
'#ab12cd12',
// rgb
'rgb(255, 10, 20)',
'rgb(100%, 10%, 20%)',
'rgba(255, 10, 20)',
'rgba(100%, 10%, 20%)',
'rgba(255, 10, 20, 0.5)',
'rgba(100%, 10%, 20%, 0.5)',
'rgba(255, 10, 20, 50%)',
'rgba(100%, 10%, 20%, 50%)',
// hsl
'hsl(100, 50%, 60%)',
'hsl(100, 50.5%, 60.5%)',
'hsla(100, 50%, 60%)',
'hsla(100, 50.5%, 60.5%)',
'hsla(100, 50%, 60%, 0.5)',
'hsla(100, 50.5%, 60.5%, 0.5)',
'hsla(100, 50%, 60%, 50%)',
'hsla(100, 50.5%, 60.5%, 50%)',
// invalid here
'invalid string',
'(hsla(100, 100, 100))',
'hsla(100, 100, 100',
// invalid numbers
'#zzab99',
'#abcdef0',
'rgb(255%, 100, 100)',
'rgb(255%, 100, -10)',
'rgb(100%, 100, -10)',
'hsl(370, 100, 10)',
'hsl(200, 100%, 160%)',
];
foreach ($css_colors as $color) {
$check = Colors::validateColor($color);
print "Color check: $color with (" . Colors::ALL . "): ";
if ($check) {
print '<span style="color: green;">OK</span>';
} else {
print '<span style="color: red;">ERROR</span>';
}
print "<br>";
}
echo "<hr>";
// valid rgb/hsl checks
$color = 'hsla(360, 100%, 60%, 0.556)';
$check = Colors::validateColor($color);
print "Color check: $color with (" . Colors::ALL . "): ";
if ($check) {
print '<span style="color: green;">OK</span>';
} else {
print '<span style="color: red;">ERROR</span>';
}
// invalid flag
echo "<hr>";
try {
$check = Colors::validateColor('#ab12cd', 99);
print "No Exception";
} catch (\Exception $e) {
print "ERROR: " . $e->getCode() . ": " . $e->getMessage() . "<br>";
}
// error message
print $log->printErrorMsg();
print "</body></html>";
// __END__

View File

@@ -22,7 +22,7 @@ define('USE_DATABASE', false);
// sample config
require 'config.php';
// define log file id
$LOG_FILE_ID = 'classTest-colors';
$LOG_FILE_ID = 'classTest-convert-colors';
ob_end_flush();
use CoreLibs\Convert\Colors;
@@ -40,7 +40,7 @@ $log = new CoreLibs\Debug\Logging([
]);
$color_class = 'CoreLibs\Convert\Colors';
$PAGE_NAME = 'TEST CLASS: COLORS';
$PAGE_NAME = 'TEST CLASS: CONVERT COLORS';
print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
print "<body>";

View File

@@ -118,7 +118,8 @@ print "<b>TRUNCATE test_foobar</b><br>";
$query = "TRUNCATE test_foobar";
$db->dbExec($query);
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
$status = $db->dbExec("INSERT INTO test_foo (test, number_a) VALUES "
. "('FOO TEST " . time() . "', 1) RETURNING test, number_a");
print "DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "DB OBJECT: <pre>" . print_r($status, true) . "</pre>| "
@@ -127,6 +128,29 @@ print "DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
var_dump($db->dbGetReturningExt());
// same as above but use an EOM string
$some_time = time();
$query = <<<EOM
INSERT INTO test_foo (
test, number_a
) VALUES (
'EOM FOO TEST $some_time', 1
)
RETURNING test, number_a
EOM;
$status = $db->dbExec($query);
print "EOM STRING DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "DB OBJECT: <pre>" . print_r($status, true) . "</pre>| "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
var_dump($db->dbGetReturningExt());
// should throw deprecated error
// $db->getReturningExt();
print "DIRECT INSERT PREVIOUS INSERTED: "
@@ -145,6 +169,28 @@ print "PREPARE INSERT[ins_test_foo] STATUS: " . Support::printToString($status)
print "PREPARE INSERT PREVIOUS INSERTED: "
. print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo "
. "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "<br>";
print "PREPARE CURSOR RETURN:<br>";
foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
print "KEY: " . $key . ': ' . $db->dbGetPrepareCursorValue('ins_test_foo', $key) . "<br>";
}
$query = <<<EOM
INSERT INTO test_foo (
test
) VALUES (
$1
)
RETURNING test
EOM;
$db->dbPrepare("ins_test_foo_eom", $query);
$status = $db->dbExecute("ins_test_foo_eom", ['EOM BAR TEST ' . time()]);
print "EOM STRING PREPARE INSERT[ins_test_foo_eom] STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// returning test with multiple entries
// $status = $db->db_exec(
// "INSERT INTO test_foo (test) VALUES "
@@ -167,6 +213,26 @@ print "DIRECT MULTIPLE INSERT WITH RETURN STATUS: " . Support::printToString($st
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
$t_1 = time();
$t_2 = time();
$t_3 = time();
$query = <<<EOM
INSERT INTO test_foo (
test
) VALUES
('EOM BAR 1 $t_1'),
('EOM BAR 2 $t_2'),
('EOM BAR 3 $t_3')
RETURNING test_foo_id, test
EOM;
$status = $db->dbExec($query);
print "EOM STRING DIRECT MULTIPLE INSERT WITH RETURN STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "PRIMARY KEYS: " . print_r($db->dbGetInsertPK(), true) . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// no returning, but not needed ;
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO; TEST " . time() . "')");
print "DIRECT INSERT NO RETURN STATUS: " . Support::printToString($status) . " |<br>"
@@ -235,6 +301,24 @@ if ($db->dbPrepare('sel_test_foo', $q_prep) === false) {
. $db->dbGetLastError() . "/" . $db->dbGetLastWarning() . "/"
. "<pre>" . print_r($db->dbGetCombinedErrorHistory(), true) . "</pre><br>";
}
echo "<hr>";
print "EOM STYLE STRINGS<br>";
$test_bar = $db->dbEscapeLiteral('SOMETHING DIFFERENT');
// Test EOM block
$q = <<<EOM
SELECT test_foo_id, test, some_bool, string_a, number_a,
-- comment
number_a_numeric, some_time
FROM test_foo
WHERE test = $test_bar
ORDER BY test_foo_id DESC LIMIT 5
EOM;
while (is_array($res = $db->dbReturn($q))) {
print "ROW: <pre>" . print_r($res, true) . "</pre><br>";
}
echo "<hr>";
// NOTE: try to replacate connection still exists if script is run a second time
// open pg bouncer connection
$db_pgb = new CoreLibs\DB\IO($DB_CONFIG['test_pgbouncer'], $log);

View File

@@ -27,6 +27,10 @@ $ECHO_ALL = true;
$LOG_FILE_ID = 'classTest-form';
ob_end_flush();
// start session, needed for Form\Generate
$SET_SESSION_NAME = EDIT_SESSION_NAME;
$session = new CoreLibs\Create\Session($SET_SESSION_NAME);
// define an array for page use
$table_arrays = [];
$table_arrays[\CoreLibs\Get\System::getPageName(1)] = [

View File

@@ -54,8 +54,9 @@ print "<html><head><title>TEST CLASS</title><head>";
print "<body>";
print '<div><a href="class_test.db.php">Class Test: DB</a></div>';
print '<div><a href="class_test.db.DbReturn.php">Class Test: DB dbReturn</a></div>';
print '<div><a href="class_test.colors.php">Class Test: COLORS</a></div>';
print '<div><a href="class_test.db.dbReturn.php">Class Test: DB dbReturn</a></div>';
print '<div><a href="class_test.convert.colors.php">Class Test: CONVERT COLORS</a></div>';
print '<div><a href="class_test.check.colors.php">Class Test: CHECK COLORS</a></div>';
print '<div><a href="class_test.mime.php">Class Test: MIME</a></div>';
print '<div><a href="class_test.json.php">Class Test: JSON</a></div>';
print '<div><a href="class_test.token.php">Class Test: FORM TOKEN</a></div>';
@@ -84,6 +85,7 @@ print '<div><a href="class_test.output.form.php">Class Test: OUTPUT FORM</a></di
print '<div><a href="class_test.admin.backend.php">Class Test: BACKEND ADMIN CLASS</a></div>';
print '<div><a href="class_test.lang.php">Class Test: LANG/L10n</a></div>';
print '<div><a href="class_test.session.php">Class Test: SESSION</a></div>';
print '<div><a href="class_test.session.read.php">Class Test: SESSION: READ</a></div>';
print '<div><a href="class_test.smarty.php">Class Test: SMARTY</a></div>';
print '<div><a href="class_test.login.php">Class Test: LOGIN</a></div>';
print '<div><a href="class_test.autoloader.php">Class Test: AUTOLOADER</a></div>';

52
www/composer.lock generated
View File

@@ -9,30 +9,30 @@
"packages-dev": [
{
"name": "doctrine/instantiator",
"version": "1.4.1",
"version": "1.5.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
"reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
"reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
"doctrine/coding-standard": "^9 || ^11",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"vimeo/psalm": "^4.22"
"vimeo/psalm": "^4.30 || ^5.4"
},
"type": "library",
"autoload": {
@@ -59,7 +59,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
"source": "https://github.com/doctrine/instantiator/tree/1.4.1"
"source": "https://github.com/doctrine/instantiator/tree/1.5.0"
},
"funding": [
{
@@ -75,7 +75,7 @@
"type": "tidelift"
}
],
"time": "2022-03-03T08:28:38+00:00"
"time": "2022-12-30T00:15:36+00:00"
},
{
"name": "myclabs/deep-copy",
@@ -138,16 +138,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.15.1",
"version": "v4.15.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"shasum": ""
},
"require": {
@@ -188,9 +188,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
},
"time": "2022-09-04T07:30:47+00:00"
"time": "2022-11-12T15:38:23+00:00"
},
{
"name": "phar-io/manifest",
@@ -305,16 +305,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.17",
"version": "9.2.23",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
"reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"shasum": ""
},
"require": {
@@ -370,7 +370,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
},
"funding": [
{
@@ -378,7 +378,7 @@
"type": "github"
}
],
"time": "2022-08-30T12:24:04+00:00"
"time": "2022-12-28T12:41:10+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -623,16 +623,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.25",
"version": "9.5.27",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d"
"reference": "a2bc7ffdca99f92d959b3f2270529334030bba38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"reference": "3e6f90ca7e3d02025b1d147bd8d4a89fd4ca8a1d",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38",
"reference": "a2bc7ffdca99f92d959b3f2270529334030bba38",
"shasum": ""
},
"require": {
@@ -705,7 +705,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.25"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27"
},
"funding": [
{
@@ -721,7 +721,7 @@
"type": "tidelift"
}
],
"time": "2022-09-25T03:44:45+00:00"
"time": "2022-12-09T07:31:23+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -23,23 +23,8 @@
declare(strict_types=1);
$DEBUG_ALL = true;
$PRINT_ALL = true;
$ECHO_ALL = false;
$DB_DEBUG = true;
// TODO: only extract _POST data that is needed
extract($_POST, EXTR_SKIP);
ob_start();
require 'config.php';
// overrride debug flags
if (!DEBUG) {
$DEBUG_ALL = false;
$PRINT_ALL = false;
$DB_DEBUG = false;
$ECHO_ALL = false;
}
// should be utf8
header("Content-type: text/html; charset=" . DEFAULT_ENCODING);
@@ -51,14 +36,16 @@ $log = new CoreLibs\Debug\Logging([
'file_id' => LOG_FILE_ID . 'EditBase',
'print_file_date' => true,
'per_class' => true,
'debug_all' => $DEBUG_ALL,
'echo_all' => $ECHO_ALL,
'print_all' => $PRINT_ALL,
'debug_all' => $DEBUG_ALL ?? false,
'echo_all' => $ECHO_ALL ?? false,
'print_all' => $PRINT_ALL ?? false,
]);
// db connection
$db = new CoreLibs\DB\IO(DB_CONFIG, $log);
// login page
$login = new CoreLibs\ACL\Login($db, $log, $session);
// space for setting special debug flags
// $login->log->setLogLevelAll('debug', true);
// lang, path, domain
// pre auto detect language after login
$locale = \CoreLibs\Language\GetLocale::setLocale();
@@ -70,493 +57,10 @@ $l10n = new \CoreLibs\Language\L10n(
);
// flush and start
ob_end_flush();
// turn off set log per class
$log->setLogPer('class', false);
// create form class
$form = new CoreLibs\Output\Form\Generate(DB_CONFIG, $log, $l10n, $locale);
if ($form->mobile_phone) {
echo "I am sorry, but this page cannot be viewed by a mobile phone";
exit;
}
// smarty template engine (extended Translation version)
$smarty = new CoreLibs\Template\SmartyExtend($l10n, $locale);
// $form->log->debug('POST', $form->log->prAr($_POST));
if (TARGET == 'live' || TARGET == 'remote') {
// login
$login->log->setLogLevelAll('debug', DEBUG ? true : false);
$login->log->setLogLevelAll('echo', false);
$login->log->setLogLevelAll('print', DEBUG ? true : false);
// form
$form->log->setLogLevelAll('debug', DEBUG ? true : false);
$form->log->setLogLevelAll('echo', false);
$form->log->setLogLevelAll('print', DEBUG ? true : false);
}
// space for setting special debug flags
$login->log->setLogLevelAll('debug', true);
// set smarty arrays
$HEADER = [];
$DATA = [];
$DEBUG_DATA = [];
// set the template dir
// WARNING: this has a special check for the mailing tool layout (old layout)
if (defined('LAYOUT')) {
$smarty->setTemplateDir(BASE . INCLUDES . TEMPLATES . CONTENT_PATH);
$DATA['css'] = LAYOUT . CSS;
$DATA['js'] = LAYOUT . JS;
} else {
$smarty->setTemplateDir(TEMPLATES);
$DATA['css'] = CSS;
$DATA['js'] = JS;
}
// set table width
$table_width = '100%';
$ADMIN_STYLESHEET = 'edit.css';
// define all needed smarty stuff for the general HTML/page building
$HEADER['CSS'] = CSS;
$HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING;
$HEADER['STYLESHEET'] = $ADMIN_STYLESHEET ?? ADMIN_STYLESHEET;
if ($form->my_page_name == 'edit_order') {
// get is for "table_name" and "where" only
$table_name = $_GET['table_name'] ?? '';
// $where = $_GET['where'] ?? '';
// order name is _always_ order_number for the edit interface
// follwing arrays do exist here:
// $position ... has the positions of the [0..max], cause in a <select>
// I can't put an number into the array field, in this array,
// there are the POSITION stored, that should CHANGE there order (up/down)
// $row_data_id ... has ALL ids from the sorting part
// $row_data_order ... has ALL order positions from the soirting part
if (!isset($position)) {
$position = [];
}
$row_data_id = $_POST['row_data_id'] ?? [];
$original_id = $row_data_id;
if (count($position)) {
$row_data_order = $_POST['row_data_order'];
// FIRST u have to put right sort, then read again ...
// hast to be >0 or the first one is selected and then there is no move
if (isset($up) && isset($position[0]) && $position[0] > 0) {
for ($i = 0; $i < count($position); $i++) {
// change position order
// this gets temp, id before that, gets actual (moves one "down")
// this gets the old before (moves one "up")
// is done for every element in row
// echo "A: ".$row_data_id[$position[$i]]
// ." (".$row_data_order[$position[$i]].") -- ".$row_data_id[$position[$i]-1]
// ." (".$row_data_order[$position[$i]-1].")<br>";
$temp_id = $row_data_id[$position[$i]] ?? null;
$row_data_id[$position[$i]] = $row_data_id[$position[$i] - 1] ?? null;
$row_data_id[$position[$i] - 1] = $temp_id;
// echo "A: ".$row_data_id[$position[$i]]
// ." (".$row_data_order[$position[$i]].") -- "
// .$row_data_id[$position[$i]-1]." (".$row_data_order[$position[$i]-1].")<br>";
} // for
} // if up
// the last position id from position array is not to be the count - 1 of
// row_data_id array, or it is the last element
if (isset($down) && ($position[count($position) - 1] != (count($row_data_id) - 1))) {
for ($i = count($position) - 1; $i >= 0; $i--) {
// same as up, just up in other way, starts from bottom (last element) and moves "up"
// element before actuel gets temp, this element, becomes element after this,
// element after this, gets this
$temp_id = $row_data_id[$position[$i] + 1] ?? null;
$row_data_id[$position[$i] + 1] = $row_data_id[$position[$i]] ?? null;
$row_data_id[$position[$i]] = $temp_id;
} // for
} // if down
// write data ... (which has to be abstrackt ...)
if (
(isset($up) && $position[0] > 0) ||
(isset($down) && ($position[count($position) - 1] != (count($row_data_id) - 1)))
) {
for ($i = 0; $i < count($row_data_id); $i++) {
if (isset($row_data_order[$i]) && isset($row_data_id[$i])) {
$q = "UPDATE " . $table_name
. " SET order_number = " . $row_data_order[$i]
. " WHERE " . $table_name . "_id = " . $row_data_id[$i];
$q = $form->dbExec($q);
}
} // for all article ids ...
} // if write
} // if there is something to move
// get ...
$q = "SELECT " . $table_name . "_id, name, order_number FROM " . $table_name . " ";
if (!empty($where_string)) {
$q .= "WHERE $where_string ";
}
$q .= "ORDER BY order_number";
// init arrays
$row_data = [];
$options_id = [];
$options_name = [];
$options_selected = [];
// DB read data for menu
while (is_array($res = $form->dbReturn($q))) {
$row_data[] = [
"id" => $res[$table_name . "_id"],
"name" => $res["name"],
"order" => $res["order_number"]
];
} // while read data ...
// html title
$HEADER['HTML_TITLE'] = $form->l->__('Edit Order');
$messages = [];
// error msg
if (isset($error)) {
if (!isset($msg)) {
$msg = [];
}
$messages[] = [
'msg' => $msg,
'class' => 'error',
'width' => '100%'
];
}
$DATA['form_error_msg'] = $messages;
// all the row data
for ($i = 0; $i < count($row_data); $i++) {
$options_id[] = $i;
$options_name[] = $row_data[$i]['name'];
// list of points to order
for ($j = 0; $j < count($position); $j++) {
// if matches, put into select array
if (
isset($original_id[$position[$j]]) && isset($row_data[$i]['id']) &&
$original_id[$position[$j]] == $row_data[$i]['id']
) {
$options_selected[] = $i;
}
}
}
$DATA['options_id'] = $options_id;
$DATA['options_name'] = $options_name;
$DATA['options_selected'] = $options_selected;
// hidden list for the data (id, order number)
$row_data_id = [];
$row_data_order = [];
for ($i = 0; $i < count($row_data); $i++) {
$row_data_id[] = $row_data[$i]['id'];
$row_data_order[] = $row_data[$i]['order'];
}
$DATA['row_data_id'] = $row_data_id;
$DATA['row_data_order'] = $row_data_order;
// hidden names for the table & where string
$DATA['table_name'] = $table_name;
$DATA['where_string'] = $where_string ?? '';
$EDIT_TEMPLATE = 'edit_order.tpl';
} else {
// load call only if id is set
if (isset(${$form->archive_pk_name})) {
$form->formProcedureLoad(${$form->archive_pk_name});
}
$form->formProcedureNew();
$form->formProcedureSave();
$form->formProcedureDelete();
// delete call only if those two are set
if (isset($element_list) && isset($remove_name)) {
$form->formProcedureDeleteFromElementList($element_list, $remove_name);
}
$DATA['table_width'] = $table_width;
$messages = [];
// write out error / status messages
$messages[] = $form->formPrintMsg();
$DATA['form_error_msg'] = $messages;
// MENU START
// request some session vars
if (!isset($HEADER_COLOR)) {
$DATA['HEADER_COLOR'] = '#E0E2FF';
} else {
$DATA['HEADER_COLOR'] = $_SESSION['HEADER_COLOR'];
}
$DATA['USER_NAME'] = $_SESSION['USER_NAME'];
$DATA['EUID'] = $_SESSION['EUID'];
$DATA['GROUP_NAME'] = $_SESSION['GROUP_NAME'];
$DATA['GROUP_LEVEL'] = $_SESSION['GROUP_ACL_LEVEL'];
$PAGES = $_SESSION['PAGES'];
//$form->log->debug('menu', $form->log->prAr($PAGES));
// build nav from $PAGES ...
if (!isset($PAGES) || !is_array($PAGES)) {
$PAGES = [];
}
$menuarray = [];
foreach ($PAGES as $PAGE_CUID => $PAGE_DATA) {
if ($PAGE_DATA['menu'] && $PAGE_DATA['online']) {
$menuarray[] = $PAGE_DATA;
}
}
// split point for nav points
$COUNT_NAV_POINTS = count($menuarray);
$SPLIT_FACTOR = 3;
$START_SPLIT_COUNT = 3;
// WTF ?? I dunno what I am doing here ...
for ($i = 9; $i < $COUNT_NAV_POINTS; $i += $START_SPLIT_COUNT) {
if ($COUNT_NAV_POINTS > $i) {
$SPLIT_FACTOR += 1;
}
}
$position = 0;
$menu_data = [];
// for ($i = 1; $i <= count($menuarray); $i ++) {
foreach ($menuarray as $i => $data) {
// do that for new array
$j = $i + 1;
$menu_data[$i]['pagename'] = htmlentities($data['page_name']);
$menu_data[$i]['filename'] =
// prefix folder or host name
(isset($data['hostname']) && $data['hostname'] ?
$data['hostname'] :
''
)
// filename
. ($data['filename'] ?? '')
// query string
. (isset($data['query_string']) && $data['query_string'] ?
$data['query_string'] :
''
);
if ($j == 1 || !($i % $SPLIT_FACTOR)) {
$menu_data[$i]['splitfactor_in'] = 1;
} else {
$menu_data[$i]['splitfactor_in'] = 0;
}
// on matching, we also need to check if we are in the same folder
if (
isset($data['filename']) &&
$data['filename'] == \CoreLibs\Get\System::getPageName() &&
(!isset($data['hostname']) || (
isset($data['hostname']) &&
(!$data['hostname'] || strstr($data['hostname'], CONTENT_PATH) !== false)
))
) {
$position = $i;
$menu_data[$i]['position'] = 1;
$menu_data[$i]['popup'] = 0;
} else {
// add query stuff
// HAS TO DONE LATER ... set urlencode, etc ...
// check if popup needed
if (isset($data['popup']) && $data['popup'] == 1) {
$menu_data[$i]['popup'] = 1;
$menu_data[$i]['rand'] = uniqid((string)rand());
$menu_data[$i]['width'] = $data['popup_x'];
$menu_data[$i]['height'] = $data['popup_y'];
} else {
$menu_data[$i]['popup'] = 0;
}
$menu_data[$i]['position'] = 0;
} // highlight or not
if (!($j % $SPLIT_FACTOR) || (($j + 1) > count($menuarray))) {
$menu_data[$i]['splitfactor_out'] = 1;
} else {
$menu_data[$i]['splitfactor_out'] = 0;
}
} // for
// $form->log->debug('MENU ARRAY', $form->log->prAr($menu_data));
$DATA['menu_data'] = $menu_data;
$DATA['page_name'] = $menuarray[$position]['page_name'] ?? '-Undefined [' . $position . '] -';
$L_TITLE = $DATA['page_name'];
// html title
$HEADER['HTML_TITLE'] = $form->l->__($L_TITLE);
// END MENU
// LOAD AND NEW
$DATA['load'] = $form->formCreateLoad();
$DATA['new'] = $form->formCreateNew();
// SHOW DATA PART
if ($form->yes) {
$DATA['form_yes'] = $form->yes;
$DATA['form_my_page_name'] = $form->my_page_name;
$DATA['filename_exist'] = 0;
$DATA['drop_down_input'] = 0;
$elements = [];
// depending on the "getPageName()" I show different stuff
switch ($form->my_page_name) {
case 'edit_users':
$elements[] = $form->formCreateElement('login_error_count');
$elements[] = $form->formCreateElement('login_error_date_last');
$elements[] = $form->formCreateElement('login_error_date_first');
$elements[] = $form->formCreateElement('enabled');
$elements[] = $form->formCreateElement('deleted');
$elements[] = $form->formCreateElement('protected');
$elements[] = $form->formCreateElement('username');
$elements[] = $form->formCreateElement('password');
$elements[] = $form->formCreateElement('password_change_interval');
$elements[] = $form->formCreateElement('login_user_id');
$elements[] = $form->formCreateElement('login_user_id_set_date');
$elements[] = $form->formCreateElement('login_user_id_last_revalidate');
$elements[] = $form->formCreateElement('login_user_id_locked');
$elements[] = $form->formCreateElement('login_user_id_revalidate_after');
$elements[] = $form->formCreateElement('login_user_id_valid_from');
$elements[] = $form->formCreateElement('login_user_id_valid_until');
$elements[] = $form->formCreateElement('email');
$elements[] = $form->formCreateElement('last_name');
$elements[] = $form->formCreateElement('first_name');
$elements[] = $form->formCreateElement('edit_group_id');
$elements[] = $form->formCreateElement('edit_access_right_id');
$elements[] = $form->formCreateElement('strict');
$elements[] = $form->formCreateElement('locked');
$elements[] = $form->formCreateElement('lock_until');
$elements[] = $form->formCreateElement('lock_after');
$elements[] = $form->formCreateElement('admin');
$elements[] = $form->formCreateElement('debug');
$elements[] = $form->formCreateElement('db_debug');
$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');
$elements[] = $form->formCreateElement('name');
$elements[] = $form->formCreateElement('header_color');
$elements[] = $form->formCreateElement('template');
break;
case 'edit_pages':
if (!isset($form->table_array['edit_page_id']['value'])) {
$q = "DELETE FROM temp_files";
$form->dbExec($q);
// gets all files in the current dir and dirs given ending with .php
$folders = ['../admin/', '../frontend/'];
$files = ['*.php'];
$search_glob = [];
foreach ($folders as $folder) {
// make sure this folder actually exists
if (is_dir(ROOT . $folder)) {
foreach ($files as $file) {
$search_glob[] = $folder . $file;
}
}
}
$crap = exec('ls ' . join(' ', $search_glob), $output, $status);
// now get all that are NOT in de DB
$q = "INSERT INTO temp_files (folder, filename) VALUES ";
$t_q = '';
foreach ($output as $output_file) {
// split the ouput into folder and file
$pathinfo = pathinfo($output_file);
if (!empty($pathinfo['dirname'])) {
$pathinfo['dirname'] .= DIRECTORY_SEPARATOR;
} else {
$pathinfo['dirname'] = '';
}
if ($t_q) {
$t_q .= ', ';
}
$t_q .= "('" . $form->dbEscapeString($pathinfo['dirname']) . "', '"
. $form->dbEscapeString($pathinfo['basename']) . "')";
}
$form->dbExec($q . $t_q, 'NULL');
$elements[] = $form->formCreateElement('filename');
} else {
// show file menu
// just show name of file ...
$DATA['filename_exist'] = 1;
$DATA['filename'] = $form->table_array['filename']['value'];
} // File Name View IF
$elements[] = $form->formCreateElement('hostname');
$elements[] = $form->formCreateElement('name');
// $elements[] = $form->formCreateElement('tag');
// $elements[] = $form->formCreateElement('min_acl');
$elements[] = $form->formCreateElement('order_number');
$elements[] = $form->formCreateElement('online');
$elements[] = $form->formCreateElement('menu');
$elements[] = $form->formCreateElementListTable('edit_query_string');
$elements[] = $form->formCreateElement('content_alias_edit_page_id');
$elements[] = $form->formCreateElementListTable('edit_page_content');
$elements[] = $form->formCreateElement('popup');
$elements[] = $form->formCreateElement('popup_x');
$elements[] = $form->formCreateElement('popup_y');
$elements[] = $form->formCreateElementReferenceTable('edit_visible_group');
$elements[] = $form->formCreateElementReferenceTable('edit_menu_group');
break;
case 'edit_languages':
$elements[] = $form->formCreateElement('enabled');
$elements[] = $form->formCreateElement('short_name');
$elements[] = $form->formCreateElement('long_name');
$elements[] = $form->formCreateElement('iso_name');
break;
case 'edit_groups':
$elements[] = $form->formCreateElement('enabled');
$elements[] = $form->formCreateElement('name');
$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');
$elements[] = $form->formCreateElement('flag');
break;
case 'edit_menu_group':
$elements[] = $form->formCreateElement('name');
$elements[] = $form->formCreateElement('flag');
$elements[] = $form->formCreateElement('order_number');
break;
case 'edit_access':
$elements[] = $form->formCreateElement('name');
$elements[] = $form->formCreateElement('enabled');
$elements[] = $form->formCreateElement('protected');
$elements[] = $form->formCreateElement('color');
$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]';
break;
}
// $form->log->debug('edit', "Elements: <pre>".$form->log->prAr($elements));
$DATA['elements'] = $elements;
$DATA['hidden'] = $form->formCreateHiddenFields();
$DATA['save_delete'] = $form->formCreateSaveDelete();
} else {
$DATA['form_yes'] = 0;
}
$EDIT_TEMPLATE = 'edit_body.tpl';
}
// debug data, if DEBUG flag is on, this data is print out
$DEBUG_DATA['DEBUG'] = $DEBUG_TMPL ?? '';
// create main data array
$CONTENT_DATA = array_merge($HEADER, $DATA, $DEBUG_DATA);
// data is 1:1 mapping (all vars, values, etc)
foreach ($CONTENT_DATA as $key => $value) {
$smarty->assign($key, $value);
}
if (is_dir(BASE . TEMPLATES_C)) {
$smarty->setCompileDir(BASE . TEMPLATES_C);
}
if (is_dir(BASE . CACHE)) {
$smarty->setCacheDir(BASE . CACHE);
}
$smarty->display($EDIT_TEMPLATE, 'editAdmin_' . $smarty->lang, 'editAdmin_' . $smarty->lang);
$form->log->debug('DEBUGEND', '==================================== [Form END]');
// debug output
echo $login->log->printErrorMsg();
echo $form->log->printErrorMsg();
// init smarty and form class
$edit_base = new CoreLibs\Admin\EditBase(DB_CONFIG, $log, $l10n, $locale);
// creates edit pages and runs actions
$edit_base->editBaseRun();
// __END__

View File

@@ -1,110 +0,0 @@
<?php
declare(strict_types=1);
$edit_access = [
'table_array' => [
'edit_access_id' => [
'value' => $GLOBALS['edit_access_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Access Group Name',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumericspace|unique'
],
'description' => [
'value' => $GLOBALS['description'] ?? '',
'output_name' => 'Description',
'type' => 'textarea'
],
'color' => [
'value' => $GLOBALS['color'] ?? '',
'output_name' => 'Color',
'mandatory' => 0,
'type' => 'text',
'size' => 6,
'length' => 6,
'error_check' => 'custom',
'error_regex' => "/[\dA-Fa-f]{6}/",
'error_example' => 'F6A544'
],
'enabled' => [
'value' => $GLOBALS['enabled'] ?? 0,
'output_name' => 'Enabled',
'type' => 'binary',
'int' => 1, // OR 'bool' => 1
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'protected' => [
'value' => $GLOBALS['protected'] ?? 0,
'output_name' => 'Protected',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'additional_acl' => [
'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",
'show_fields' => [
[
'name' => 'name'
],
],
'element_list' => [
'edit_access_data' => [
'output_name' => 'Edit Access Data',
'delete_name' => 'remove_edit_access_data',
// 'type' => 'reference_data', // is not a sub table read and connect, but only a sub table with data
'max_empty' => 5, // maxium visible if no data is set, if filled add this number to visible
'prefix' => 'ead',
'elements' => [
'name' => [
'type' => 'text',
'error_check' => 'alphanumeric|unique',
'output_name' => 'Name',
'mandatory' => 1
],
'value' => [
'type' => 'text',
'output_name' => 'Value'
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1]
],
/*'edit_access_id' => [
'int' => 1,
'type' => 'hidden',
'fk_id' => 1 // reference main key from master table above
],*/
'edit_access_data_id' => [
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
],
],
],
];
// __END__

View File

@@ -1,111 +0,0 @@
<?php
declare(strict_types=1);
$edit_groups = [
'table_array' => [
'edit_group_id' => [
'value' => $GLOBALS['edit_group_id'] ?? '',
'pk' => 1,
'type' => 'hidden'
],
'enabled' => [
'value' => $GLOBALS['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Group Name',
'type' => 'text',
'mandatory' => 1
],
'edit_access_right_id' => [
'value' => $GLOBALS['edit_access_right_id'] ?? '',
'output_name' => 'Group Level',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_scheme_id' => [
'value' => $GLOBALS['edit_scheme_id'] ?? '',
'output_name' => 'Group Scheme',
'int_null' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_scheme_id, name FROM edit_scheme WHERE enabled = 1 ORDER BY name"
],
'additional_acl' => [
'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',
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'Enabled: '
],
],
'element_list' => [
'edit_page_access' => [
'output_name' => 'Pages',
'mandatory' => 1,
'delete' => 0, // set then reference entries are deleted, else the 'enable' flag is only set
'enable_name' => 'enable_page_access',
'prefix' => 'epa',
'read_data' => [
'table_name' => 'edit_page',
'pk_id' => 'edit_page_id',
'name' => 'name',
'order' => 'order_number'
],
'elements' => [
'edit_page_access_id' => [
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'int' => 1,
'preset' => 1, // first of the select
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_page_id' => [
'int' => 1,
'type' => 'hidden'
],
/*,
'edit_default' => [
'output_name' => 'Default',
'type' => 'radio',
'mandatory' => 1
],*/
],
], // edit pages ggroup
],
];
// __END__

View File

@@ -1,77 +0,0 @@
<?php
declare(strict_types=1);
$edit_languages = [
'table_array' => [
'edit_language_id' => [
'value' => $GLOBALS['edit_language_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'short_name' => [
'value' => $GLOBALS['short_name'] ?? '',
'output_name' => 'Language (short)',
'mandatory' => 1,
'type' => 'text',
'size' => 2,
'length' => 2
],
'long_name' => [
'value' => $GLOBALS['long_name'] ?? '',
'output_name' => 'Language (long)',
'mandatory' => 1,
'type' => 'text',
'size' => 40
],
'iso_name' => [
'value' => $GLOBALS['iso_name'] ?? '',
'output_name' => 'ISO Code',
'mandatory' => 1,
'type' => 'text'
],
'order_number' => [
'value' => $GLOBALS['order_number'] ?? '',
'int' => 1,
'order' => 1
],
'enabled' => [
'value' => $GLOBALS['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'lang_default' => [
'value' => $GLOBALS['lang_default'] ?? '',
'output_name' => 'Default Language',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
],
'load_query' => "SELECT edit_language_id, long_name, iso_name, enabled FROM edit_language ORDER BY long_name",
'show_fields' => [
[
'name' => 'long_name'
],
[
'name' => 'iso_name',
'before_value' => 'ISO: '
],
[
'name' => 'enabled',
'before_value' => 'Enabled: ',
'binary' => ['Yes','No'],
],
],
'table_name' => 'edit_language'
];
// __END__

View File

@@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
$edit_menu_group = [
'table_array' => [
'edit_menu_group_id' => [
'value' => $GLOBALS['edit_menu_group_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Group name',
'mandatory' => 1,
'type' => 'text'
],
'flag' => [
'value' => $GLOBALS['flag'] ?? '',
'output_name' => 'Flag',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumeric|unique'
],
'order_number' => [
'value' => $GLOBALS['order_number'] ?? '',
'output_name' => 'Group order',
'type' => 'order',
'int' => 1,
'order' => 1
],
],
'table_name' => 'edit_menu_group',
'load_query' => "SELECT edit_menu_group_id, name FROM edit_menu_group ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
],
];
// __END__

View File

@@ -1,249 +0,0 @@
<?php
declare(strict_types=1);
$edit_pages = [
'table_array' => [
'edit_page_id' => [
'value' => $GLOBALS['edit_page_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'filename' => [
'value' => $GLOBALS['filename'] ?? '',
'output_name' => 'Add File ...',
'mandatory' => 1,
'type' => 'drop_down_db',
'query' => "SELECT DISTINCT temp_files.filename AS id, temp_files.folder || temp_files.filename AS name "
. "FROM temp_files "
. "LEFT JOIN edit_page ep ON temp_files.filename = ep.filename "
. "WHERE ep.filename IS NULL"
],
'hostname' => [
'value' => $GLOBALS['hostname'] ?? '',
'output_name' => 'Hostname or folder',
'type' => 'text'
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Page name',
'mandatory' => 1,
'type' => 'text'
],
'order_number' => [
'value' => $GLOBALS['order_number'] ?? '',
'output_name' => 'Page order',
'type' => 'order',
'int' => 1,
'order' => 1
],
/* 'flag' => [
'value' => isset($GLOBALS['flag']) ? $GLOBALS['flag'] : '',
'output_name' => 'Page Flag',
'type' => 'drop_down_array',
'query' => [
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4',
'5' => '5'
],
],*/
'online' => [
'value' => $GLOBALS['online'] ?? '',
'output_name' => 'Online',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'menu' => [
'value' => $GLOBALS['menu'] ?? '',
'output_name' => 'Menu',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'popup' => [
'value' => $GLOBALS['popup'] ?? '',
'output_name' => 'Popup',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'popup_x' => [
'value' => $GLOBALS['popup_x'] ?? '',
'output_name' => 'Popup Width',
'int_null' => 1,
'type' => 'text',
'size' => 4,
'length' => 4
],
'popup_y' => [
'value' => $GLOBALS['popup_y'] ?? '',
'output_name' => 'Popup Height',
'int_null' => 1,
'type' => 'text',
'size' => 4,
'length' => 4
],
'content_alias_edit_page_id' => [
'value' => $GLOBALS['content_alias_edit_page_id'] ?? '',
'output_name' => 'Content Alias Source',
'int_null' => 1,
'type' => 'drop_down_db',
// query creation
'select_distinct' => 0,
'pk_name' => 'edit_page_id AS content_alias_edit_page_id',
'input_name' => 'name',
'table_name' => 'edit_page',
'where_not_self' => 1,
'order_by' => 'order_number'
// 'query' => "SELECT edit_page_id AS content_alias_edit_page_id, name ".
// "FROM edit_page ".
// (isset($GLOBALS['edit_page_id']) ? " WHERE edit_page_id <> ".$GLOBALS['edit_page_id'] : "")." ".
// "ORDER BY order_number"
],
],
'load_query' => "SELECT edit_page_id, "
. "CASE WHEN hostname IS NOT NULL THEN hostname ELSE ''::VARCHAR END || filename AS filename, "
. "name, online, menu, popup "
. "FROM edit_page "
. "ORDER BY order_number",
'table_name' => 'edit_page',
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'filename',
'before_value' => 'Filename: '
],
[
'name' => 'online',
'binary' => ['Yes', 'No'],
'before_value' => 'Online: '
],
[
'name' => 'menu',
'binary' => ['Yes', 'No'],
'before_value' => 'Menu: '
],
[
'name' => 'popup',
'binary' => ['Yes', 'No'],
'before_value' => 'Popup: '
],
],
'reference_arrays' => [
'edit_visible_group' => [
'table_name' => 'edit_page_visible_group',
'other_table_pk' => 'edit_visible_group_id',
'output_name' => 'Visible Groups (access)',
'mandatory' => 1,
'select_size' => 10,
'selected' => $GLOBALS['edit_visible_group_id'] ?? '',
'query' => "SELECT edit_visible_group_id, 'Name: ' || name || ', ' || 'Flag: ' || flag "
. "FROM edit_visible_group ORDER BY name"
],
'edit_menu_group' => [
'table_name' => 'edit_page_menu_group',
'other_table_pk' => 'edit_menu_group_id',
'output_name' => 'Menu Groups (grouping)',
'mandatory' => 1,
'select_size' => 10,
'selected' => $GLOBALS['edit_menu_group_id'] ?? '',
'query' => "SELECT edit_menu_group_id, 'Name: ' || name || ', ' || 'Flag: ' || flag "
. "FROM edit_menu_group ORDER BY order_number"
],
],
'element_list' => [
'edit_query_string' => [
'output_name' => 'Query Strings',
'delete_name' => 'remove_query_string',
'prefix' => 'eqs',
'elements' => [
'name' => [
'output_name' => 'Name',
'type' => 'text',
'error_check' => 'unique|alphanumeric',
'mandatory' => 1
],
'value' => [
'output_name' => 'Value',
'type' => 'text'
],
'enabled' => [
'output_name' => 'Enabled',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'dynamic' => [
'output_name' => 'Dynamic',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'edit_query_string_id' => [
'type' => 'hidden',
'pk_id' => 1
],
], // elements
], // query_string element list
'edit_page_content' => [
'output_name' => 'Page Content',
'delete_name' => 'remove_page_content',
'prefix' => 'epc',
'elements' => [
'name' => [
'output_name' => 'Content',
'type' => 'text',
'error_check' => 'alphanumeric',
'mandatory' => 1
],
'uid' => [
'output_name' => 'UID',
'type' => 'text',
'error_check' => 'unique|alphanumeric',
'mandatory' => 1
],
'order_number' => [
'output_name' => 'Order',
'type' => 'text',
'error_check' => 'int',
'mandatory' => 1
],
'online' => [
'output_name' => 'Online',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'int' => 1,
'preset' => 1, // first of the select
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_page_content_id' => [
'type' => 'hidden',
'pk_id' => 1
],
],
],
], // element list
];
// __END__

View File

@@ -1,59 +0,0 @@
<?php
declare(strict_types=1);
$edit_schemes = [
'table_array' => [
'edit_scheme_id' => [
'value' => $GLOBALS['edit_scheme_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Scheme Name',
'mandatory' => 1,
'type' => 'text'
],
'header_color' => [
'value' => $GLOBALS['header_color'] ?? '',
'output_name' => 'Header Color',
'mandatory' => 1,
'type' => 'text',
'size' => 6,
'length' => 6,
'error_check' => 'custom',
'error_regex' => '/[\dA-Fa-f]{6}/',
'error_example' => 'F6A544'
],
'enabled' => [
'value' => $GLOBALS['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'template' => [
'value' => $GLOBALS['template'] ?? '',
'output_name' => 'Template',
'type' => 'text'
],
],
'table_name' => 'edit_scheme',
'load_query' => "SELECT edit_scheme_id, name, enabled FROM edit_scheme ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'Enabled: '
],
],
]; // main array
// __END__

View File

@@ -1,426 +0,0 @@
<?php
declare(strict_types=1);
$edit_users = [
'table_array' => [
'edit_user_id' => [
'value' => $GLOBALS['edit_user_id'] ?? '',
'type' => 'hidden',
'pk' => 1,
'int' => 1
],
'username' => [
'value' => $GLOBALS['username'] ?? '',
'output_name' => 'Username',
'mandatory' => 1,
'error_check' => 'unique|alphanumericextended',
'type' => 'text',
// if not min_edit_acl only read
// if not min_show_acl not visible
'min_edit_acl' => '100',
'min_show_acl' => '-1',
],
'password' => [
'value' => $GLOBALS['password'] ?? '',
'HIDDEN_value' => $GLOBALS['HIDDEN_password'] ?? '',
'CONFIRM_value' => $GLOBALS['CONFIRM_password'] ?? '',
'output_name' => 'Password',
'mandatory' => 1,
'type' => 'password', // later has to be password for encryption in database
'update' => [ // connected field updates, and update data
'password_change_date' => [ // db row to update
'type' => 'date', // type of field (int/text/date/etc)
'value' => 'NOW()' // value [todo: complex reference
],
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
// password date when first insert and password is set, needs special field with connection to password
// password reset force interval, if set, user needs to reset password after X time period
'password_change_interval' => [
'value' => $GLOBALS['password_change_interval'] ?? '',
'output_name' => 'Password change interval',
// can be any date length format. n Y/M/D [not H/M/S], only one set, no combination
'error_check' => 'intervalshort',
'type' => 'text',
'interval' => 1, // interval needs NULL write for empty
'size' => 5, // make it 5 chars long
'length' => 5,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'enabled' => [
'value' => $GLOBALS['enabled'] ?? '',
'output_name' => 'Enabled',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '-1',
],
'deleted' => [
'value' => $GLOBALS['deleted'] ?? '',
'output_name' => 'Deleted',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'strict' => [
'value' => $GLOBALS['strict'] ?? '',
'output_name' => 'Strict (Lock after errors)',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'locked' => [
'value' => $GLOBALS['locked'] ?? '',
'output_name' => 'Locked (auto set if strict with errors)',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'admin' => [
'value' => $GLOBALS['admin'] ?? '',
'output_name' => 'Admin',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'debug' => [
'value' => $GLOBALS['debug'] ?? '',
'output_name' => 'Debug',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'db_debug' => [
'value' => $GLOBALS['db_debug'] ?? '',
'output_name' => 'DB Debug',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'email' => [
'value' => $GLOBALS['email'] ?? '',
'output_name' => 'E-Mail',
'type' => 'text',
'error_check' => 'email',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'last_name' => [
'value' => $GLOBALS['last_name'] ?? '',
'output_name' => 'Last Name',
'type' => 'text',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'first_name' => [
'value' => $GLOBALS['first_name'] ?? '',
'output_name' => 'First Name',
'type' => 'text',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'lock_until' => [
'value' => $GLOBALS['lock_until'] ?? '',
'output_name' => 'Lock account until',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'lock_after' => [
'value' => $GLOBALS['lock_after'] ?? '',
'output_name' => 'Lock account after',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id' => [
'value' => $GLOBALS['login_user_id'] ?? '',
'output_name' => '_GET/_POST loginUserId direct login ID',
'type' => 'text',
'error_check' => 'unique|custom',
'error_regex' => "/^[A-Za-z0-9]+$/",
'emptynull' => 1,'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_set_date' => [
'output_name' => 'loginUserId set date',
'value' => $GLOBALS['login_user_id_set_date'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_user_id_last_revalidate' => [
'output_name' => 'loginUserId last revalidate date',
'value' => $GLOBALS['login_user_id_last_revalidate'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_user_id_locked' => [
'value' => $GLOBALS['login_user_id_locked'] ?? '',
'output_name' => 'loginUserId usage locked',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_revalidate_after' => [
'value' => $GLOBALS['login_user_id_revalidate_after'] ?? '',
'output_name' => 'loginUserId, User must login after n days',
'type' => 'text',
'error_check' => 'intervalshort',
'interval' => 1, // interval needs NULL write for empty
'size' => 5, // make it 5 chars long
'length' => 5,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_valid_from' => [
'value' => $GLOBALS['login_user_id_valid_from'] ?? '',
'output_name' => 'loginUserId valid from',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_valid_until' => [
'value' => $GLOBALS['login_user_id_valid_until'] ?? '',
'output_name' => 'loginUserId valid until',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_language_id' => [
'value' => $GLOBALS['edit_language_id'] ?? '',
'output_name' => 'Language',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_language_id, long_name FROM edit_language WHERE enabled = 1 ORDER BY order_number",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_scheme_id' => [
'value' => $GLOBALS['edit_scheme_id'] ?? '',
'output_name' => 'Scheme',
'int_null' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_scheme_id, name FROM edit_scheme WHERE enabled = 1 ORDER BY name",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_group_id' => [
'value' => $GLOBALS['edit_group_id'] ?? '',
'output_name' => 'Group',
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_group_id, name FROM edit_group WHERE enabled = 1 ORDER BY name",
'mandatory' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_access_right_id' => [
'value' => $GLOBALS['edit_access_right_id'] ?? '',
'output_name' => 'User Level',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_error_count' => [
'output_name' => 'Login error count',
'value' => $GLOBALS['login_error_count'] ?? '',
'type' => 'view',
'empty' => '0',
'min_show_acl' => '100',
],
'login_error_date_last' => [
'output_name' => 'Last login error',
'value' => $GLOBALS['login_error_date_liast'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_error_date_first' => [
'output_name' => 'First login error',
'value' => $GLOBALS['login_error_date_first'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'protected' => [
'value' => $GLOBALS['protected'] ?? '',
'output_name' => 'Protected',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'additional_acl' => [
'value' => $GLOBALS['additional_acl'] ?? '',
'output_name' => 'Additional ACL (as JSON)',
'type' => 'textarea',
'error_check' => 'json',
'rows' => 10,
'cols' => 60,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
],
'load_query' => "SELECT edit_user_id, username, enabled, deleted, "
. "strict, locked, login_error_count "
. "FROM edit_user "
// if base acl is not 90 only list enabled
// if not admin flag, do not list admin flagged
. (
!$GLOBALS['acl_admin'] ?
"WHERE admin = 0 "
. (
$GLOBALS['base_acl_level'] < 90 ?
"AND enabled = 1 " :
""
)
: ''
)
. "ORDER BY username",
'table_name' => 'edit_user',
'show_fields' => [
[
'name' => 'username'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'ENBL: '
],
[
'name' => 'deleted',
'binary' => ['Yes', 'No'],
'before_value' => 'DEL: '
],
[
'name' => 'strict',
'binary' => ['Yes', 'No'],
'before_value' => 'STRC: '
],
[
'name' => 'locked',
'binary' => ['Yes', 'No'],
'before_value' => 'LCK: '
],
[
'name' => 'login_error_count',
'before_value' => 'ERR: '
],
],
'element_list' => [
'edit_access_user' => [
'output_name' => 'Accounts',
'mandatory' => 1,
// set then reference entries are deleted, else the 'enable' flag is only set
'delete' => 0,
// acl
'min_edit_acl' => '40',
'min_show_acl' => '20',
// table read prefix
'prefix' => 'ecu',
'read_data' => [
'table_name' => 'edit_access',
'pk_id' => 'edit_access_id',
'name' => 'name',
'order' => 'name'
],
'elements' => [
'edit_access_user_id' => [
'output_name' => 'Activate',
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'preset' => 1, // first of the select
'int' => 1,
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_default' => [
'type' => 'radio_group',
'output_name' => 'Default',
'int' => 1,
'element_list' => 'radio_group'
],
'edit_access_id' => [
'type' => 'hidden',
'int' => 1
],
],
], // edit pages ggroup
],
];
// __END__

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
$edit_visible_group = [
'table_array' => [
'edit_visible_group_id' => [
'value' => $GLOBALS['edit_visible_group_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $GLOBALS['name'] ?? '',
'output_name' => 'Group name',
'mandatory' => 1,
'type' => 'text'
],
'flag' => [
'value' => $GLOBALS['flag'] ?? '',
'output_name' => 'Flag',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumeric|unique'
],
],
'table_name' => 'edit_visible_group',
'load_query' => "SELECT edit_visible_group_id, name FROM edit_visible_group ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
],
];
// __END__

View File

@@ -8,6 +8,7 @@
********************************************************************
*}
<!doctype html>
<html>
<head>
<title>{$HTML_TITLE}</title>

View File

@@ -51,7 +51,6 @@
{* not yet implemented *}
{/if}
{if $element.type == 'order'}
{* <input type="button" name="order" value="{$element.data.output_name}" OnClick="pop('order.php?col_name={$element.data.col_name}&table_name={$element.data.table_name}&where={$element.data.query}','Order','status=no,scrollbars=yes,width=700,height=500');"> *}
<input type="button" name="order" value="{$element.data.output_name}" OnClick="pop('edit_order.php?table_name={$element.data.table_name}&where={$element.data.query}','Order','status=no,scrollbars=yes,width=700,height=500');">
<input type="hidden" name="{$element.data.name}" value="{$element.data.value}">
{/if}
@@ -69,8 +68,20 @@
</select>
{/if}
{if $element.type == 'element_list'}
<script language="JavaScript">
function deleteElement(delete_name, line_item)
{
let confirm_val = confirm('{t}Do you want to remove this entry?{/t}');
if (confirm_val === false) {
return false;
}
document.getElementById(delete_name).value = line_item;
document.getElementById(delete_name + '_flag').value = confirm_val;
document.edit_form.submit();
}
</script>
{* each row of data *}
<table width="100%" border="0">
<table width="100%" border="0" cellspacing="0" cellpadding="2">
{foreach from=$element.data.content item=line key=key}
<tr>
{* now each line of data *}
@@ -107,7 +118,7 @@
{/if}
{* if there is a hidden key, set delete, but only if we have a delete string *}
{if $element.data.type.$line_key == 'hidden' && $line_item && $element.data.delete_name}
<input type="submit" name="remove_button" value="{t}Delete{/t}" onClick="document.edit_form.{$element.data.delete_name}.value={$line_item};document.edit_form.{$element.data.delete_name}_flag.value=confirm('{t}Do you want to remove this entry?{/t}');document.edit_form.submit();">
<input type="button" name="remove_button" value="{t}Delete{/t}" onClick="deleteElement('{$element.data.delete_name}', '{$line_item}');">
{/if}
{if $element.data.type.$line_key == 'hidden' && $element.data.enable_name && $element.data.delete && $element.data.output_name.$line_key}
<input type="checkbox" name="{$element.data.enable_name}[{$key}]" value="1" {if $line_item}checked{/if}> {$element.data.output_name.$line_key}

View File

@@ -8,6 +8,7 @@
********************************************************************
*}
<!doctype html>
<html>
<head>
<title>{$HTML_TITLE}</title>

View File

@@ -8,6 +8,7 @@
********************************************************************
*}
<!doctype html>
<html>
<head>
<title>{$HTML_TITLE}</title>

View File

@@ -8,6 +8,7 @@
********************************************************************
*}
<!doctype html>
<html>
<head>
<title>{$HTML_TITLE}</title>

View File

@@ -19,7 +19,7 @@ body {
background-color: white;
color: black;
font-family: Verdana,Arial,Helvetica,sans-serif;
font-size : 8pt;
font-size : 9pt;
}
.large {
@@ -455,4 +455,11 @@ input[type="text"]:focus, textarea:focus, select:focus {
background-color: #FFDF6F;
}
td.edit_fgcolor tr:nth-child(odd) {
background-color: #e2e2c5;
}
td.edit_fgcolor tr:nth-child(even) {
background-color: #ffffcd;
}
/* ***************************** ADMIN EDIT INTERFACE COLORS ********************************* */

View File

@@ -1014,8 +1014,12 @@ function phfo(tree)
} else if (tree.content) {
content.push(tree.content);
}
// if not input close
if (tree.tag != 'input') {
// if not input, image or br, then close
if (
tree.tag != 'input' ||
tree.tag != 'img' ||
tree.tag != 'br'
) {
content.push('</' + tree.tag + '>');
}
// combine to string

View File

@@ -1,13 +1,13 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.ja = {}));
}(this, function (exports) { 'use strict';
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ja = {}));
}(this, (function (exports) { 'use strict';
var fp = typeof window !== "undefined" && window.flatpickr !== undefined
? window.flatpickr
: {
l10ns: {}
l10ns: {},
};
var Japanese = {
weekdays: {
@@ -20,7 +20,7 @@
"木曜日",
"金曜日",
"土曜日",
]
],
},
months: {
shorthand: [
@@ -50,11 +50,15 @@
"10月",
"11月",
"12月",
]
],
},
time_24hr: true,
rangeSeparator: " から ",
firstDayOfWeek: 1
monthAriaLabel: "月",
amPM: ["午前", "午後"],
yearAriaLabel: "年",
hourAriaLabel: "時間",
minuteAriaLabel: "分",
};
fp.l10ns.ja = Japanese;
var ja = fp.l10ns;
@@ -64,4 +68,4 @@
Object.defineProperty(exports, '__esModule', { value: true });
}));
})));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -677,9 +677,20 @@ class Login
$_SESSION['GROUP_ACL_TYPE'] = $res['group_type'];
// deprecated TEMPLATE setting
$_SESSION['TEMPLATE'] = $res['template'] ? $res['template'] : '';
$_SESSION['HEADER_COLOR'] = $res['second_header_color'] ?
$_SESSION['HEADER_COLOR'] = !empty($res['second_header_color']) ?
$res['second_header_color'] :
$res['first_header_color'];
// missing # before, this is for legacy data, will be deprecated
if (preg_match("/^[\dA-Fa-f]{6,8}$/", $_SESSION['HEADER_COLOR'])) {
$_SESSION['HEADER_COLOR'] = '#' . $_SESSION['HEADER_COLOR'];
}
// TODO: make sure that header color is valid:
// # + 6 hex
// # + 8 hex (alpha)
// rgb(), rgba(), hsl(), hsla()
// rgb: nnn.n for each
// hsl: nnn.n for first, nnn.n% for 2nd, 3rd
// Check\Colors::validateColor()
$_SESSION['LANG'] = $res['locale'] ?? 'en';
$_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8';
$_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG']
@@ -1622,7 +1633,7 @@ EOM;
$this->session->checkActiveSession() === true &&
!empty($_SESSION['DEFAULT_LOCALE'])
) {
$locale = $_SESSION['DEFAULT_LOCALE'] ?? '';
$locale = $_SESSION['DEFAULT_LOCALE'];
} else {
$locale = (defined('SITE_LOCALE') && !empty(SITE_LOCALE)) ?
SITE_LOCALE :

View File

@@ -0,0 +1,588 @@
<?php
/*********************************************************************
* AUTHOR: Clemens Schwaighofer
* CREATED: 2023/1/6
* DESCRIPTION:
* Original created: 2003/06/10
* This is the edit_base.php data as is moved into a class so we can
* more easy update this and also move to a different AJAX style more
* easy
*********************************************************************/
declare(strict_types=1);
namespace CoreLibs\Admin;
use Exception;
use SmartyException;
class EditBase
{
/** @var array<mixed> */
private $HEADER = [];
/** @var array<mixed> */
private $DATA = [];
/** @var array<mixed> */
private $DEBUG_DATA = [];
/** @var string the template name */
private $EDIT_TEMPLATE = '';
/** @var \CoreLibs\Template\SmartyExtend smarty system */
private $smarty;
/** @var \CoreLibs\Output\Form\Generate form generate system */
private $form;
/** @var \CoreLibs\Debug\Logging */
public $log;
/**
* construct form generator
*
* @param array<mixed> $db_config db config array, mandatory
* @param \CoreLibs\Debug\Logging $log Logging class, null auto set
* @param \CoreLibs\Language\L10n $l10n l10n language class, null auto set
* @param array<string,string> $locale locale array from ::setLocale,
* null auto set
*/
public function __construct(
array $db_config,
\CoreLibs\Debug\Logging $log,
\CoreLibs\Language\L10n $l10n,
array $locale
) {
$this->log = $log;
// smarty template engine (extended Translation version)
$this->smarty = new \CoreLibs\Template\SmartyExtend($l10n, $locale);
// turn off set log per class
$log->setLogPer('class', false);
// create form class
$this->form = new \CoreLibs\Output\Form\Generate(
$db_config,
$log,
$l10n,
$locale
);
if ($this->form->mobile_phone) {
echo "I am sorry, but this page cannot be viewed by a mobile phone";
exit;
}
// $this->form->log->debug('POST', $this->form->log->prAr($_POST));
}
/**
* edit order page
*
* @return void
*/
private function editOrderPage(): void
{
// get is for "table_name" and "where" only
$table_name = $_GET['table_name'] ?? $_POST['table_name'] ?? '';
// not in use
// $where_string = $_GET['where'] ?? $_POST['where'] ?? '';
// order name is _always_ order_number for the edit interface
// follwing arrays do exist here:
// $position ... has the positions of the [0..max], cause in a <select>
// I can't put an number into the array field, in this array,
// there are the POSITION stored,
// that should CHANGE there order (up/down)
// $row_data_id ... has ALL ids from the sorting part
// $row_data_order ... has ALL order positions from the soirting part
$position = $_POST['position'] ?? [];
$row_data_id = $_POST['row_data_id'] ?? [];
$original_id = $row_data_id;
$row_data_order = $_POST['row_data_order'] ?? [];
// direction
$up = $_POST['up'] ?? '';
$down = $_POST['down'] ?? '';
if (count($position)) {
// FIRST u have to put right sort, then read again ...
// hast to be >0 or the first one is selected and then there is no move
if (!empty($up) && isset($position[0]) && $position[0] > 0) {
for ($i = 0; $i < count($position); $i++) {
// change position order
// this gets temp, id before that, gets actual (moves one "down")
// this gets the old before (moves one "up")
// is done for every element in row
// echo "A: ".$row_data_id[$position[$i]]
// ." (".$row_data_order[$position[$i]].") -- ".$row_data_id[$position[$i]-1]
// ." (".$row_data_order[$position[$i]-1].")<br>";
$temp_id = $row_data_id[$position[$i]] ?? null;
$row_data_id[$position[$i]] = $row_data_id[(int)$position[$i] - 1] ?? null;
$row_data_id[(int)$position[$i] - 1] = $temp_id;
// echo "A: ".$row_data_id[$position[$i]]
// ." (".$row_data_order[$position[$i]].") -- "
// .$row_data_id[$position[$i]-1]." (".$row_data_order[$position[$i]-1].")<br>";
} // for
} // if up
// the last position id from position array is not to be the count - 1 of
// row_data_id array, or it is the last element
if (!empty($down) && ($position[count($position) - 1] != (count($row_data_id) - 1))) {
for ($i = count($position) - 1; $i >= 0; $i--) {
// same as up, just up in other way, starts from bottom (last element) and moves "up"
// element before actuel gets temp, this element, becomes element after this,
// element after this, gets this
$temp_id = $row_data_id[(int)$position[$i] + 1] ?? null;
$row_data_id[(int)$position[$i] + 1] = $row_data_id[$position[$i]] ?? null;
$row_data_id[$position[$i]] = $temp_id;
} // for
} // if down
// write data ... (which has to be abstrackt ...)
if (
(!empty($up) && $position[0] > 0) ||
(!empty($down) && ($position[count($position) - 1] != (count($row_data_id) - 1)))
) {
for ($i = 0; $i < count($row_data_id); $i++) {
if (isset($row_data_order[$i]) && isset($row_data_id[$i])) {
$q = "UPDATE " . $table_name
. " SET order_number = " . $row_data_order[$i]
. " WHERE " . $table_name . "_id = " . $row_data_id[$i];
$q = $this->form->dbExec($q);
}
} // for all article ids ...
} // if write
} // if there is something to move
// get ...
$q = "SELECT " . $table_name . "_id, name, order_number FROM " . $table_name . " ";
// /* if (!empty($where_string)) {
// $q .= "WHERE $where_string ";
// } */
$q .= "ORDER BY order_number";
// init arrays
$row_data = [];
$options_id = [];
$options_name = [];
$options_selected = [];
// DB read data for menu
while (is_array($res = $this->form->dbReturn($q))) {
$row_data[] = [
"id" => $res[$table_name . "_id"],
"name" => $res["name"],
"order" => $res["order_number"]
];
} // while read data ...
// html title
$this->HEADER['HTML_TITLE'] = $this->form->l->__('Edit Order');
$messages = [];
$error = $_POST['error'] ?? 0;
// error msg
if (!empty($error)) {
$msg = $_POST['msg'] ?? [];
if (!is_array($msg)) {
$msg = [];
}
$messages[] = [
'msg' => $msg,
'class' => 'error',
'width' => '100%'
];
}
$this->DATA['form_error_msg'] = $messages;
// all the row data
for ($i = 0; $i < count($row_data); $i++) {
$options_id[] = $i;
$options_name[] = $row_data[$i]['name'];
// list of points to order
for ($j = 0; $j < count($position); $j++) {
// if matches, put into select array
if (
isset($original_id[$position[$j]]) && isset($row_data[$i]['id']) &&
$original_id[$position[$j]] == $row_data[$i]['id']
) {
$options_selected[] = $i;
}
}
}
$this->DATA['options_id'] = $options_id;
$this->DATA['options_name'] = $options_name;
$this->DATA['options_selected'] = $options_selected;
// hidden list for the data (id, order number)
$row_data_id = [];
$row_data_order = [];
for ($i = 0; $i < count($row_data); $i++) {
$row_data_id[] = $row_data[$i]['id'];
$row_data_order[] = $row_data[$i]['order'];
}
$this->DATA['row_data_id'] = $row_data_id;
$this->DATA['row_data_order'] = $row_data_order;
// hidden names for the table & where string
$this->DATA['table_name'] = $table_name;
$this->DATA['where_string'] = '';
// $this->DATA['where_string'] = $where_string ?? '';
$this->EDIT_TEMPLATE = 'edit_order.tpl';
}
/**
* all edit pages
*
* @return void
*/
private function editPageFlow(): void
{
// set table width
$table_width = '100%';
// load call only if id is set
if (!empty($_POST[$this->form->archive_pk_name])) {
$this->form->formProcedureLoad($_POST[$this->form->archive_pk_name]);
}
$this->form->formProcedureNew();
$this->form->formProcedureSave();
$this->form->formProcedureDelete();
// delete call only if those two are set
// and we are not in new/save/master delete
if (
!$this->form->new &&
!$this->form->save &&
!$this->form->delete &&
!empty($_POST['element_list']) &&
!empty($_POST['remove_name'])
) {
$this->form->formProcedureDeleteFromElementList(
$_POST['element_list'],
$_POST['remove_name']
);
// run a load post element delete to not end up with empty page
$this->form->formLoadTableArray($_POST[$this->form->archive_pk_name]);
$this->form->yes = 1;
}
$this->DATA['table_width'] = $table_width;
$messages = [];
// write out error / status messages
$messages[] = $this->form->formPrintMsg();
$this->DATA['form_error_msg'] = $messages;
// MENU START
// request some session vars
if (empty($_SESSION['HEADER_COLOR'])) {
$this->DATA['HEADER_COLOR'] = '#E0E2FF';
} else {
$this->DATA['HEADER_COLOR'] = $_SESSION['HEADER_COLOR'];
}
$this->DATA['USER_NAME'] = $_SESSION['USER_NAME'];
$this->DATA['EUID'] = $_SESSION['EUID'];
$this->DATA['GROUP_NAME'] = $_SESSION['GROUP_NAME'];
$this->DATA['GROUP_LEVEL'] = $_SESSION['GROUP_ACL_LEVEL'];
$PAGES = $_SESSION['PAGES'];
//$this->form->log->debug('menu', $this->form->log->prAr($PAGES));
// build nav from $PAGES ...
if (!isset($PAGES) || !is_array($PAGES)) {
$PAGES = [];
}
$menuarray = [];
foreach ($PAGES as $PAGE_CUID => $PAGE_DATA) {
if ($PAGE_DATA['menu'] && $PAGE_DATA['online']) {
$menuarray[] = $PAGE_DATA;
}
}
// split point for nav points
$COUNT_NAV_POINTS = count($menuarray);
$SPLIT_FACTOR = 3;
$START_SPLIT_COUNT = 3;
// WTF ?? I dunno what I am doing here ...
for ($i = 9; $i < $COUNT_NAV_POINTS; $i += $START_SPLIT_COUNT) {
if ($COUNT_NAV_POINTS > $i) {
$SPLIT_FACTOR += 1;
}
}
$position = 0;
$menu_data = [];
// for ($i = 1; $i <= count($menuarray); $i ++) {
foreach ($menuarray as $i => $menu_element) {
// do that for new array
$j = $i + 1;
$menu_data[$i]['pagename'] = htmlentities($menu_element['page_name']);
$menu_data[$i]['filename'] =
// prefix folder or host name
(isset($menu_element['hostname']) && $menu_element['hostname'] ?
$menu_element['hostname'] :
''
)
// filename
. ($menu_element['filename'] ?? '')
// query string
. (isset($menu_element['query_string']) && $menu_element['query_string'] ?
$menu_element['query_string'] :
''
);
if ($j == 1 || !($i % $SPLIT_FACTOR)) {
$menu_data[$i]['splitfactor_in'] = 1;
} else {
$menu_data[$i]['splitfactor_in'] = 0;
}
// on matching, we also need to check if we are in the same folder
if (
isset($menu_element['filename']) &&
$menu_element['filename'] == \CoreLibs\Get\System::getPageName() &&
(!isset($menu_element['hostname']) || (
isset($menu_element['hostname']) &&
(!$menu_element['hostname'] || strstr($menu_element['hostname'], CONTENT_PATH) !== false)
))
) {
$position = $i;
$menu_data[$i]['position'] = 1;
$menu_data[$i]['popup'] = 0;
} else {
// add query stuff
// HAS TO DONE LATER ... set urlencode, etc ...
// check if popup needed
if (isset($menu_element['popup']) && $menu_element['popup'] == 1) {
$menu_data[$i]['popup'] = 1;
$menu_data[$i]['rand'] = uniqid((string)rand());
$menu_data[$i]['width'] = $menu_element['popup_x'];
$menu_data[$i]['height'] = $menu_element['popup_y'];
} else {
$menu_data[$i]['popup'] = 0;
}
$menu_data[$i]['position'] = 0;
} // highlight or not
if (!($j % $SPLIT_FACTOR) || (($j + 1) > count($menuarray))) {
$menu_data[$i]['splitfactor_out'] = 1;
} else {
$menu_data[$i]['splitfactor_out'] = 0;
}
} // for
// $this->form->log->debug('MENU ARRAY', $this->form->log->prAr($menu_data));
$this->DATA['menu_data'] = $menu_data;
$this->DATA['page_name'] = $menuarray[$position]['page_name'] ?? '-Undefined [' . $position . '] -';
$L_TITLE = $this->DATA['page_name'];
// html title
$this->HEADER['HTML_TITLE'] = $this->form->l->__($L_TITLE);
// END MENU
// LOAD AND NEW
$this->DATA['load'] = $this->form->formCreateLoad();
$this->DATA['new'] = $this->form->formCreateNew();
// SHOW DATA PART
if ($this->form->yes) {
$this->DATA['form_yes'] = $this->form->yes;
$this->DATA['form_my_page_name'] = $this->form->my_page_name;
$this->DATA['filename_exist'] = 0;
$this->DATA['drop_down_input'] = 0;
$elements = [];
// depending on the "getPageName()" I show different stuff
switch ($this->form->my_page_name) {
case 'edit_users':
$elements[] = $this->form->formCreateElement('login_error_count');
$elements[] = $this->form->formCreateElement('login_error_date_last');
$elements[] = $this->form->formCreateElement('login_error_date_first');
$elements[] = $this->form->formCreateElement('enabled');
$elements[] = $this->form->formCreateElement('deleted');
$elements[] = $this->form->formCreateElement('protected');
$elements[] = $this->form->formCreateElement('username');
$elements[] = $this->form->formCreateElement('password');
$elements[] = $this->form->formCreateElement('password_change_interval');
$elements[] = $this->form->formCreateElement('login_user_id');
$elements[] = $this->form->formCreateElement('login_user_id_set_date');
$elements[] = $this->form->formCreateElement('login_user_id_last_revalidate');
$elements[] = $this->form->formCreateElement('login_user_id_locked');
$elements[] = $this->form->formCreateElement('login_user_id_revalidate_after');
$elements[] = $this->form->formCreateElement('login_user_id_valid_from');
$elements[] = $this->form->formCreateElement('login_user_id_valid_until');
$elements[] = $this->form->formCreateElement('email');
$elements[] = $this->form->formCreateElement('last_name');
$elements[] = $this->form->formCreateElement('first_name');
$elements[] = $this->form->formCreateElement('edit_group_id');
$elements[] = $this->form->formCreateElement('edit_access_right_id');
$elements[] = $this->form->formCreateElement('strict');
$elements[] = $this->form->formCreateElement('locked');
$elements[] = $this->form->formCreateElement('lock_until');
$elements[] = $this->form->formCreateElement('lock_after');
$elements[] = $this->form->formCreateElement('admin');
$elements[] = $this->form->formCreateElement('debug');
$elements[] = $this->form->formCreateElement('db_debug');
$elements[] = $this->form->formCreateElement('edit_language_id');
$elements[] = $this->form->formCreateElement('edit_scheme_id');
$elements[] = $this->form->formCreateElementListTable('edit_access_user');
$elements[] = $this->form->formCreateElement('additional_acl');
break;
case 'edit_schemes':
$elements[] = $this->form->formCreateElement('enabled');
$elements[] = $this->form->formCreateElement('name');
$elements[] = $this->form->formCreateElement('header_color');
$elements[] = $this->form->formCreateElement('template');
break;
case 'edit_pages':
if (!isset($this->form->table_array['edit_page_id']['value'])) {
$q = "DELETE FROM temp_files";
$this->form->dbExec($q);
// gets all files in the current dir and dirs given ending with .php
$folders = ['../admin/', '../frontend/'];
$files = ['*.php'];
$search_glob = [];
foreach ($folders as $folder) {
// make sure this folder actually exists
if (is_dir(ROOT . $folder)) {
foreach ($files as $file) {
$search_glob[] = $folder . $file;
}
}
}
$crap = exec('ls ' . join(' ', $search_glob), $output, $status);
// now get all that are NOT in de DB
$q = "INSERT INTO temp_files (folder, filename) VALUES ";
$t_q = '';
foreach ($output as $output_file) {
// split the ouput into folder and file
$pathinfo = pathinfo($output_file);
if (!empty($pathinfo['dirname'])) {
$pathinfo['dirname'] .= DIRECTORY_SEPARATOR;
} else {
$pathinfo['dirname'] = '';
}
if ($t_q) {
$t_q .= ', ';
}
$t_q .= "('" . $this->form->dbEscapeString($pathinfo['dirname']) . "', '"
. $this->form->dbEscapeString($pathinfo['basename']) . "')";
}
$this->form->dbExec($q . $t_q, 'NULL');
$elements[] = $this->form->formCreateElement('filename');
} else {
// show file menu
// just show name of file ...
$this->DATA['filename_exist'] = 1;
$this->DATA['filename'] = $this->form->table_array['filename']['value'];
} // File Name View IF
$elements[] = $this->form->formCreateElement('hostname');
$elements[] = $this->form->formCreateElement('name');
// $elements[] = $this->form->formCreateElement('tag');
// $elements[] = $this->form->formCreateElement('min_acl');
$elements[] = $this->form->formCreateElement('order_number');
$elements[] = $this->form->formCreateElement('online');
$elements[] = $this->form->formCreateElement('menu');
$elements[] = $this->form->formCreateElementListTable('edit_query_string');
$elements[] = $this->form->formCreateElement('content_alias_edit_page_id');
$elements[] = $this->form->formCreateElementListTable('edit_page_content');
$elements[] = $this->form->formCreateElement('popup');
$elements[] = $this->form->formCreateElement('popup_x');
$elements[] = $this->form->formCreateElement('popup_y');
$elements[] = $this->form->formCreateElementReferenceTable('edit_visible_group');
$elements[] = $this->form->formCreateElementReferenceTable('edit_menu_group');
break;
case 'edit_languages':
$elements[] = $this->form->formCreateElement('enabled');
$elements[] = $this->form->formCreateElement('short_name');
$elements[] = $this->form->formCreateElement('long_name');
$elements[] = $this->form->formCreateElement('iso_name');
break;
case 'edit_groups':
$elements[] = $this->form->formCreateElement('enabled');
$elements[] = $this->form->formCreateElement('name');
$elements[] = $this->form->formCreateElement('edit_access_right_id');
$elements[] = $this->form->formCreateElement('edit_scheme_id');
$elements[] = $this->form->formCreateElementListTable('edit_page_access');
$elements[] = $this->form->formCreateElement('additional_acl');
break;
case 'edit_visible_group':
$elements[] = $this->form->formCreateElement('name');
$elements[] = $this->form->formCreateElement('flag');
break;
case 'edit_menu_group':
$elements[] = $this->form->formCreateElement('name');
$elements[] = $this->form->formCreateElement('flag');
$elements[] = $this->form->formCreateElement('order_number');
break;
case 'edit_access':
$elements[] = $this->form->formCreateElement('name');
$elements[] = $this->form->formCreateElement('enabled');
$elements[] = $this->form->formCreateElement('protected');
$elements[] = $this->form->formCreateElement('color');
$elements[] = $this->form->formCreateElement('description');
// add name/value list here
$elements[] = $this->form->formCreateElementListTable('edit_access_data');
$elements[] = $this->form->formCreateElement('additional_acl');
break;
default:
print '[No valid page definition given]';
break;
}
// $this->form->log->debug('edit', "Elements: <pre>".$this->form->log->prAr($elements));
$this->DATA['elements'] = $elements;
$this->DATA['hidden'] = $this->form->formCreateHiddenFields();
$this->DATA['save_delete'] = $this->form->formCreateSaveDelete();
} else {
$this->DATA['form_yes'] = 0;
}
$this->EDIT_TEMPLATE = 'edit_body.tpl';
}
/**
* main method that either calls edit order page method or general page
* builds the smarty content and runs smarty display output
*
* @return void
* @throws Exception
* @throws SmartyException
*/
public function editBaseRun()
{
// set the template dir
// WARNING: this has a special check for the mailing tool layout (old layout)
if (defined('LAYOUT')) {
$this->smarty->setTemplateDir(BASE . INCLUDES . TEMPLATES . CONTENT_PATH);
$this->DATA['css'] = LAYOUT . CSS;
$this->DATA['js'] = LAYOUT . JS;
} else {
$this->smarty->setTemplateDir(TEMPLATES);
$this->DATA['css'] = CSS;
$this->DATA['js'] = JS;
}
$ADMIN_STYLESHEET = 'edit.css';
// define all needed smarty stuff for the general HTML/page building
$this->HEADER['CSS'] = CSS;
$this->HEADER['DEFAULT_ENCODING'] = DEFAULT_ENCODING;
/** @phpstan-ignore-next-line because ADMIN_STYLESHEET can be null */
$this->HEADER['STYLESHEET'] = $ADMIN_STYLESHEET ?? ADMIN_STYLESHEET;
// main run
if ($this->form->my_page_name == 'edit_order') {
$this->editOrderPage();
} else {
$this->editPageFlow();
}
// debug data, if DEBUG flag is on, this data is print out
// $this->DEBUG_DATA['DEBUG'] = $DEBUG_TMPL ?? '';
$this->DEBUG_DATA['DEBUG'] = '';
// create main data array
$CONTENT_DATA = array_merge($this->HEADER, $this->DATA, $this->DEBUG_DATA);
// data is 1:1 mapping (all vars, values, etc)
foreach ($CONTENT_DATA as $key => $value) {
$this->smarty->assign($key, $value);
}
if (is_dir(BASE . TEMPLATES_C)) {
$this->smarty->setCompileDir(BASE . TEMPLATES_C);
}
if (is_dir(BASE . CACHE)) {
$this->smarty->setCacheDir(BASE . CACHE);
}
$this->smarty->display(
$this->EDIT_TEMPLATE,
'editAdmin_' . $this->smarty->lang,
'editAdmin_' . $this->smarty->lang
);
$this->form->log->debug('DEBUGEND', '==================================== [Form END]');
}
}
// __END__

View File

@@ -0,0 +1,187 @@
<?php
/*
* valid checks for css/html based colors
* # hex
* # hex + alpha
* rgb
* rgba
* hsl
* hsla
*/
declare(strict_types=1);
namespace CoreLibs\Check;
use Exception;
class Colors
{
/** @var int 1 for HEX rgb */
public const HEX_RGB = 1;
/** @var int 2 for HEX rgb with alpha */
public const HEX_RGBA = 2;
/** @var int 4 for rgb() */
public const RGB = 4;
/** @var int 8 for rgba() */
public const RGBA = 8;
/** @var int 16 for hsl() */
public const HSL = 16;
/** @var int 32 for hsla() */
public const HSLA = 32;
/** @var int 63 for all bits set (sum of above) */
public const ALL = 63;
/**
* check rgb/hsl content values in detail
* will abort and return false on first error found
*
* @param string $color html/css tring to check
* @param int|false $rgb_flag flag to check for rgb
* @param int|false $hsl_flag flag to check for hsl type
* @return bool True if no error, False if error
*/
private static function rgbHslContentCheck(string $color, $rgb_flag, $hsl_flag): bool
{
// extract string between () and split into elements
preg_match("/\((.*)\)/", $color, $matches);
if (
!is_array($color_list = preg_split("/,\s*/", $matches[1] ?? ''))
) {
throw new \Exception("Could not extract color list from rgg/hsl", 3);
}
// based on rgb/hsl settings check that entries are valid
// rgb: either 0-255 OR 0-100%
// hsl: first: 0-360
foreach ($color_list as $pos => $color_check) {
if (empty($color_check)) {
return false;
}
$percent_check = false;
if (strrpos($color_check, '%', -1) !== false) {
$percent_check = true;
$color_check = str_replace('%', '', $color_check);
}
// first three normal percent or valid number
if ($rgb_flag !== false) {
if ($percent_check === true) {
// for ALL pos
if ($color_check < 0 || $color_check > 100) {
return false;
}
} elseif (
$pos < 3 &&
($color_check < 0 || $color_check > 255)
) {
return false;
} elseif (
// RGBA set pos 3 if not percent
$pos == 3 &&
($color_check < 0 || $color_check > 1)
) {
return false;
}
} elseif ($hsl_flag !== false) {
// pos 0: 0-360
// pos 1,2: %
// pos 3: % or 0-1 (float)
if (
$pos == 0 &&
($color_check < 0 || $color_check > 360)
) {
return false;
} elseif (
// if pos 1/2 are not percent
($pos == 1 || $pos == 2) &&
($percent_check != true ||
($color_check < 0 || $color_check > 100))
) {
return false;
} elseif (
// 3 is either percent or 0~1
$pos == 3 &&
(
($percent_check == false &&
($color_check < 0 || $color_check > 1)) ||
($percent_check === true &&
($color_check < 0 || $color_check > 100))
)
) {
return false;
}
}
}
return true;
}
/**
* check if html/css color string is valid
* @param string $color A color string of any format
* @param int $flags defaults to ALL, else use | to combined from
* HEX_RGB, HEX_RGBA, RGB, RGBA, HSL, HSLA
* @return bool True if valid, False if not
* @throws Exception 1: no valid flag set
*/
public static function validateColor(string $color, int $flags = self::ALL): bool
{
// blocks for each check
$regex_blocks = [];
// set what to check
if ($flags & self::HEX_RGB) {
$regex_blocks[] = '#[\dA-Fa-f]{6}';
}
if ($flags & self::HEX_RGBA) {
$regex_blocks[] = '#[\dA-Fa-f]{8}';
}
if ($flags & self::RGB) {
$regex_blocks[] = 'rgb\(\d{1,3}%?,\s*\d{1,3}%?,\s*\d{1,3}%?\)';
}
if ($flags & self::RGBA) {
$regex_blocks[] = 'rgba\(\d{1,3}%?,\s*\d{1,3}%?,\s*\d{1,3}%?(,\s*(0\.\d{1,2}|1(\.0)?|\d{1,3}%))?\)';
}
if ($flags & self::HSL) {
$regex_blocks[] = 'hsl\(\d{1,3},\s*\d{1,3}(\.\d{1})?%,\s*\d{1,3}(\.\d{1})?%\)';
}
if ($flags & self::HSLA) {
$regex_blocks[] = 'hsla\(\d{1,3},\s*\d{1,3}(\.\d{1})?%,\s*\d{1,3}'
. '(\.\d{1})?%(,\s*(0\.\d{1,2}|1(\.0)?|\d{1,3}%))?\)';
}
// wrong flag set
if ($flags > self::ALL) {
throw new \Exception("Invalid flags parameter: $flags", 1);
}
if (!count($regex_blocks)) {
throw new \Exception("No regex blocks set: $flags", 2);
}
// build regex
$regex = '^('
. join('|', $regex_blocks)
// close regex
. ')$';
// print "C: $color, F: $flags, R: $regex\n";
if (preg_match("/$regex/", $color)) {
// if valid regex, we now need to check if the content is actually valid
// only for rgb/hsl type
/** @var int|false */
$rgb_flag = strpos($color, 'rgb');
/** @var int|false */
$hsl_flag = strpos($color, 'hsl');
// if both not match, return true
if (
$rgb_flag === false &&
$hsl_flag === false
) {
return true;
}
// run detaul rgb/hsl content check
return self::rgbHslContentCheck($color, $rgb_flag, $hsl_flag);
} else {
return false;
}
}
}
// __END__

View File

@@ -28,7 +28,7 @@ class Byte
* The class itself hast the following defined
* BYTE_FORMAT_NOSPACE [1] turn off spaces between number and suffix
* BYTE_FORMAT_ADJUST [2] use sprintf to always print two decimals
* BYTE_FORMAT_SI [3] use si standard 1000 instead of bytes 1024
* BYTE_FORMAT_SI [4] use si standard 1000 instead of bytes 1024
* To use the constant from outside use class::CONSTANT
*
* @param string|int|float $bytes bytes as string int or pure int
@@ -37,6 +37,7 @@ class Byte
* BYTE_FORMAT_ADJUST: sprintf adjusted two 2 decimals
* BYTE_FORMAT_SI: use 1000 instead of 1024
* @return string converted byte number (float) with suffix
* @throws \Exception 1: no valid flag set
*/
public static function humanReadableByteFormat($bytes, int $flags = 0): string
{
@@ -61,6 +62,9 @@ class Byte
} else {
$si = false;
}
if ($flags > 7) {
throw new \Exception("Invalid flags parameter: $flags", 1);
}
// si or normal
$unit = $si ? 1000 : 1024;
@@ -109,12 +113,13 @@ class Byte
* calculates the bytes based on a string with nnG, nnGB, nnM, etc
* NOTE: large exabyte numbers will overflow
* flag allowed:
* BYTE_FORMAT_SI [3] use si standard 1000 instead of bytes 1024
* BYTE_FORMAT_SI [4] use si standard 1000 instead of bytes 1024
*
* @param string|int|float $number any string or number to convert
* @param int $flags bitwise flag with use space turned on
* BYTE_FORMAT_SI: use 1000 instead of 1024
* @return string|int|float converted value or original value
* @throws \Exception 1: no valid flag set
*/
public static function stringByteFormat($number, int $flags = 0)
{
@@ -124,6 +129,9 @@ class Byte
} else {
$si = false;
}
if ($flags != 0 && $flags != 4) {
throw new \Exception("Invalid flags parameter: $flags", 1);
}
// matches in regex
$matches = [];
// all valid units

View File

@@ -150,6 +150,9 @@ class Colors
{
// check that H is 0 to 359, 360 = 0
// and S and V are 0 to 1
if ($H == 360) {
$H = 0;
}
if ($H < 0 || $H > 359) {
return false;
}
@@ -287,6 +290,9 @@ class Colors
if (!is_numeric($hue)) {
return false;
}
if ($hue == 360) {
$hue = 0;
}
if ($hue < 0 || $hue > 359) {
return false;
}

View File

@@ -12,7 +12,7 @@
* you don't have to write any SQL queries, worry over update/insert
*
* HISTORY:
* 2019/9/11 (cs) error string 21->91, 22->92 for not overlapping with IO
* 2019/9/11 (cs) error string 21->1021, 22->1022 for not overlapping with IO
* 2005/07/07 (cs) updated array class for postgres: set 0 & NULL if int field given, insert uses () values () syntax
* 2005/03/31 (cs) fixed the class call with all debug vars
* 2003-03-10: error_ids where still wrong chagned 11->21 and 12->22
@@ -72,20 +72,24 @@ class ArrayIO extends \CoreLibs\DB\IO
// instance db_io class
parent::__construct($db_config, $log ?? new \CoreLibs\Debug\Logging());
// more error vars for this class
$this->error_string['91'] = 'No Primary Key given';
$this->error_string['92'] = 'Could not run Array Query';
$this->error_string['1999'] = 'No table array or table name set';
$this->error_string['1021'] = 'No Primary Key given';
$this->error_string['1022'] = 'Could not run Array Query';
$this->table_array = $table_array;
$this->table_name = $table_name;
// error abort if no table array or no table name
if (empty($table_array) || empty($table_name)) {
$this->__dbError(1999, false, 'MAJOR ERROR: Core settings missing');
}
// set primary key for given table_array
if (is_array($this->table_array)) {
foreach ($this->table_array as $key => $value) {
if (isset($value['pk'])) {
$this->pk_name = $key;
}
foreach ($this->table_array as $key => $value) {
if (!empty($value['pk'])) {
$this->pk_name = $key;
}
} // set pk_name IF table_array was given
}
$this->dbArrayIOSetAcl($base_acl_level, $acl_admin);
}
@@ -197,7 +201,7 @@ class ArrayIO extends \CoreLibs\DB\IO
// if not set ... produce error
if (!$this->table_array[$this->pk_name]['value']) {
// if no PK found, error ...
$this->__dbError(91);
$this->__dbError(1021);
return false;
} else {
return true;
@@ -282,7 +286,7 @@ class ArrayIO extends \CoreLibs\DB\IO
// if 0, error
$this->pk_id = null;
if (!$this->dbExec($q)) {
$this->__dbError(92);
$this->__dbError(1022);
}
return $this->table_array;
}
@@ -369,7 +373,7 @@ class ArrayIO extends \CoreLibs\DB\IO
// possible dbFetchArray errors ...
$this->pk_id = $this->table_array[$this->pk_name]['value'];
} else {
$this->__dbError(92);
$this->__dbError(1022);
}
return $this->table_array;
}
@@ -631,7 +635,7 @@ class ArrayIO extends \CoreLibs\DB\IO
}
// return success or not
if (!$this->dbExec($q)) {
$this->__dbError(92);
$this->__dbError(1022);
}
// set primary key
if ($insert) {

View File

@@ -452,6 +452,11 @@ class IO
'71' => 'Failed to set search path/schema',
'80' => 'Trying to set an empty encoding',
'81' => 'Failed to set client encoding',
// for prepared cursor return
'101' => 'Statement name empty for get prepare cursor',
'102' => 'Key empty for get prepare cursir',
'103' => 'No prepared cursor with this name',
'104' => 'No Key with this name in the prepared cursor array'
];
// load the core DB functions wrapper class
@@ -1002,7 +1007,7 @@ class IO
$this->pk_name_table[$table] : 'NULL';
}
if (
!preg_match("/ returning /i", $this->query) &&
!preg_match("/\s?returning /i", $this->query) &&
$this->pk_name && $this->pk_name != 'NULL'
) {
// check if this query has a ; at the end and remove it
@@ -1011,7 +1016,7 @@ class IO
$this->query = !is_string($__query) ? $this->query : $__query;
$this->query .= " RETURNING " . $this->pk_name;
$this->returning_id = true;
} elseif (preg_match("/ returning (.*)/i", $this->query, $matches)) {
} elseif (preg_match("/\s?returning (.*)/i", $this->query, $matches)) {
if ($this->pk_name && $this->pk_name != 'NULL') {
// add the primary key if it is not in the returning set
if (!preg_match("/$this->pk_name/", $matches[1])) {
@@ -1025,7 +1030,7 @@ class IO
// if we have an UPDATE and RETURNING, flag for true, but do not add anything
if (
$this->__checkQueryForUpdate($this->query) &&
preg_match("/ returning (.*)/i", $this->query, $matches)
preg_match("/\s?returning (.*)/i", $this->query, $matches)
) {
$this->returning_id = true;
}
@@ -1481,7 +1486,7 @@ class IO
* @param string $string string to escape
* @return string escaped string
*/
public function dbEscapeIdentifier($string): string
public function dbEscapeIdentifier(string $string): string
{
return $this->db_functions->__dbEscapeIdentifier($string);
}
@@ -1489,14 +1494,19 @@ class IO
/**
* escape data for writing to bytea type column field
* @param string $data data to escape to bytea
* @return string escaped bytea
* @return string escaped bytea string
*/
public function dbEscapeBytea($data)
public function dbEscapeBytea(string $data): string
{
return $this->db_functions->__dbEscapeBytea($data);
}
public function dbUnescapeBytea($bytea)
/**
* unescape bytea data back to normal binrary data
* @param string $bytea bytea data stream
* @return string binary data string
*/
public function dbUnescapeBytea(string $bytea): string
{
return $this->db_functions->__dbUnescapeBytea($bytea);
}
@@ -1816,6 +1826,7 @@ class IO
// if cursor exists ...
if ($this->cursor_ext[$query_hash]['cursor']) {
/** @phpstan-ignore-next-line claims this is always false, but can be true */
if ($first_call === true) {
$this->cursor_ext[$query_hash]['log'][] = 'First call';
// count the rows returned (if select)
@@ -2200,7 +2211,7 @@ class IO
public function dbGetQueryCalled(string $query): int
{
$query_hash = $this->dbGetQueryHash($query);
if ($this->query_called[$query_hash]) {
if (!empty($this->query_called[$query_hash])) {
return $this->query_called[$query_hash];
} else {
return 0;
@@ -2277,11 +2288,11 @@ class IO
$this->prepare_cursor[$stm_name]['pk_name'] = $pk_name;
}
// if no returning, then add it
if (!preg_match("/ returning /i", $query) && $this->prepare_cursor[$stm_name]['pk_name']) {
if (!preg_match("/\s?returning /i", $query) && $this->prepare_cursor[$stm_name]['pk_name']) {
$query .= " RETURNING " . $this->prepare_cursor[$stm_name]['pk_name'];
$this->prepare_cursor[$stm_name]['returning_id'] = true;
} elseif (
preg_match("/ returning (.*)/i", $query, $matches) &&
preg_match("/\s?returning (.*)/i", $query, $matches) &&
$this->prepare_cursor[$stm_name]['pk_name']
) {
// if returning exists but not pk_name, add it
@@ -3060,6 +3071,60 @@ class IO
return $this->field_names;
}
/**
* Returns the value for given key in statement
* Will write error if statemen id does not exist
* or key is invalid
*
* @param string $stm_name The name of the stored statement
* @param string $key Key field name in prepared cursor array
* Allowed are: pk_name, count, query, returning_id
* @return null|string|int|bool Entry from each of the valid keys
* Will return false on error
* Not ethat returnin_id also can return false
* but will not set an error entry
*/
public function dbGetPrepareCursorValue(string $stm_name, string $key)
{
// if no statement name
if (empty($stm_name)) {
$this->__dbError(
101,
false,
'No statement name given'
);
return false;
}
// if not a valid key
if (!in_array($key, ['pk_name', 'count', 'query', 'returning_id'])) {
$this->__dbError(
102,
false,
'Invalid key name'
);
return false;
}
// statement name not in prepared list
if (empty($this->prepare_cursor[$stm_name])) {
$this->__dbError(
103,
false,
'Statement name does not exist in prepare cursor array'
);
return false;
}
// key doest not exists, this will never hit as we filter out invalid ones
if (!isset($this->prepare_cursor[$stm_name][$key])) {
$this->__dbError(
104,
false,
'Key does not exist in prepare cursor array'
);
return false;
}
return $this->prepare_cursor[$stm_name][$key];
}
// ***************************
// ERROR AND WARNING DATA
// ***************************

View File

@@ -94,6 +94,10 @@ class DotEnv
// strip ending " and EVERYTHING that follows after that
$line = $matches[1];
}
// just be sure it is init before we fill
if (!isset($_ENV[$var])) {
$_ENV[$var] = '';
}
// strip line of slashes
$_ENV[$var] .= stripslashes($line);
}

View File

@@ -294,6 +294,9 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// language
/** @var \CoreLibs\Language\L10n */
public $l;
// log
/** @var \CoreLibs\Debug\Logging */
public $log;
// now some default error msgs (english)
/** @var array<mixed> */
@@ -307,17 +310,22 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
* @param \CoreLibs\Language\L10n|null $l10n l10n language class, null auto set
* @param array<string,string>|null $locale locale array from ::setLocale,
* null auto set
* @param array<mixed>|null $table_arrays Override table array data
* instead of try to load from
* include file
* @throws \Exception 1: No table_arrays set/no class found for my page name
*/
public function __construct(
array $db_config,
?\CoreLibs\Debug\Logging $log = null,
?\CoreLibs\Language\L10n $l10n = null,
?array $locale = null
?array $locale = null,
?array $table_arrays = null,
) {
global $table_arrays;
// replace any non valid variable names
// TODO extract only alphanumeric and _ after . to _ replacement
$this->my_page_name = str_replace(['.'], '_', System::getPageName(System::NO_EXTENSION));
// init logger if not set
$this->log = $log ?? new \CoreLibs\Debug\Logging();
// don't log per class
$this->log->setLogPer('class', false);
// if pass on locale is null
if ($locale === null) {
$locale = \CoreLibs\Language\GetLocale::setLocale();
@@ -341,58 +349,39 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// security settings
$this->base_acl_level = (int)$_SESSION['BASE_ACL_LEVEL'];
$this->acl_admin = (int)$_SESSION['ADMIN'];
$GLOBALS['base_acl_level'] = $this->base_acl_level;
$GLOBALS['acl_admin'] = $this->acl_admin;
// replace any non valid variable names and set my page name
$this->my_page_name = str_replace(
['.'],
'_',
System::getPageName(System::NO_EXTENSION)
);
// first check if we have a in page override as $table_arrays[page name]
if (
/* isset($GLOBALS['table_arrays']) &&
is_array($GLOBALS['table_arrays']) &&
isset($GLOBALS['table_arrays'][System::getPageName(System::NO_EXTENSION)]) &&
is_array($GLOBALS['table_arrays'][System::getPageName(System::NO_EXTENSION)]) */
isset($table_arrays[System::getPageName(System::NO_EXTENSION)]) &&
is_array($table_arrays[System::getPageName(System::NO_EXTENSION)])
) {
// $config_array = $GLOBALS['table_arrays'][System::getPageName(1)];
$config_array = $table_arrays[System::getPageName(1)];
} else {
// WARNING: auto spl load does not work with this as it is an array
// and not a function/object
// check if this is the old path or the new path
// check local folder in current path
// then check general global folder
if (
is_dir(TABLE_ARRAYS) &&
is_file(TABLE_ARRAYS . 'array_' . $this->my_page_name . '.php')
) {
include(TABLE_ARRAYS . 'array_' . $this->my_page_name . '.php');
} elseif (
is_dir(BASE . INCLUDES . TABLE_ARRAYS) &&
is_file(BASE . INCLUDES . TABLE_ARRAYS . 'array_' . $this->my_page_name . '.php')
) {
include(BASE . INCLUDES . TABLE_ARRAYS . 'array_' . $this->my_page_name . '.php');
}
// in the include file there must be a variable with the page name matching
if (isset(${$this->my_page_name}) && is_array(${$this->my_page_name})) {
$config_array = ${$this->my_page_name};
// primary try to load the class
/** @var \CoreLibs\Output\Form\TableArraysInterface|false $content_class */
$content_class = $this->loadTableArray();
if (is_object($content_class)) {
$config_array = $content_class->setTableArray();
} else {
// dummy created
$config_array = [
'table_array' => [],
'table_name' => '',
];
// throw an error here as we cannot load the class at all
throw new \Exception("Cannot load " . $this->my_page_name, 1);
}
}
// don't log per class
if ($log !== null) {
$log->setLogPer('class', false);
}
// $log->debug('CONFIG ARRAY', $log->prAr($config_array));
// start the array_io class which will start db_io ...
parent::__construct(
$db_config,
$config_array['table_array'],
$config_array['table_name'],
$log ?? new \CoreLibs\Debug\Logging(),
$this->log,
// set the ACL
$this->base_acl_level,
$this->acl_admin
@@ -474,8 +463,67 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
parent::__destruct();
}
// PRIVATE METHODS |=================================================>
/**
* load table array class based on my page name converted to camel case
* class files are in \TableArrays folder in \Output\Form
* @return object|bool Return class object or false on failure
*/
private function loadTableArray()
{
// note: it schould be Schemas but an original type made it to this
// this file is kept for the old usage, new one should be EditSchemas
$table_array_shim = [
'EditSchemes' => 'EditSchemas'
];
// camel case $this->my_page_name from foo_bar_note to FooBarNote
$page_name_camel_case = '';
foreach (explode('_', $this->my_page_name) as $part) {
$page_name_camel_case .= ucfirst($part);
}
$class_string = __NAMESPACE__ . "\\TableArrays\\"
. (
// shim lookup
$table_array_shim[$page_name_camel_case] ??
$page_name_camel_case
);
try {
/** @var \CoreLibs\Output\Form\TableArraysInterface|false $class */
$class = new $class_string($this);
} catch (\Throwable $t) {
$this->log->debug('CLASS LOAD', 'Failed loading: ' . $class_string . ' => ' . $t->getMessage());
return false;
}
if (is_object($class)) {
return $class;
}
return false;
}
// PUBLIC METHODS |=================================================>
/**
* return current acl admin flag (1/0)
*
* @return int Admin flag 1 for on or 0 for off
*/
public function getAclAdmin(): int
{
return $this->acl_admin;
}
/**
* check if current acl level is match to requested on
*
* @param int $level Requested ACL level
* @return bool if current level equal or larger return tru, else false
*/
public function checkBaseACL(int $level): bool
{
return $this->base_acl_level >= $level ? true : false;
}
/**
* dumps all values into output (for error msg)
*
@@ -1478,7 +1526,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// $this->log->debug('edit_error', 'QS: <pre>' . print_r($_POST, true) . '</pre>');
if (is_array($this->element_list)) {
// check the mandatory stuff
// if mandatory, check that at least on pk exists or if at least the mandatory field is filled
// if mandatory, check that at least on pk exists or
// if at least the mandatory field is filled
foreach ($this->element_list as $table_name => $reference_array) {
if (!is_array($reference_array)) {
$reference_array = [];
@@ -1518,7 +1567,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// . count($_POST[$prfx.$key]) . ' | M: $max');
// $this->log->debug('edit_error_chk', 'K: ' . $_POST[$prfx.$key] . ' | ' . $_POST[$prfx.$key][0]);
}
$this->log->debug('POST ARRAY', $this->log->prAr($_POST));
// $this->log->debug('POST ARRAY', $this->log->prAr($_POST));
// init variables before inner loop run
$mand_okay = 0;
$mand_name = '';
@@ -1530,15 +1579,17 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
for ($i = 0; $i < $max; $i++) {
// either one of the post pks is set, or the mandatory
foreach ($reference_array['elements'] as $el_name => $data_array) {
if (isset($data_array['mandatory']) && $data_array['mandatory']) {
if (
isset($data_array['mandatory']) &&
$data_array['mandatory']
) {
$mand_name = $data_array['output_name'];
}
// check if there is a primary ket inside, so it is okay
if (
isset($data_array['pk_id']) &&
count($_POST[$prfx . $el_name]) &&
isset($reference_array['mandatory']) &&
$reference_array['mandatory']
!empty($reference_array['mandatory'])
) {
$mand_okay = 1;
}
@@ -1549,15 +1600,14 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// . $_POST[$prfx . $el_name] . ' - ' . $reference_array['enable_name'] . ' - '
// . $_POST[$reference_array['enable_name']][$_POST[$prfx . $el_name][$i]]);
if (
isset($data_array['mandatory']) &&
$data_array['mandatory'] &&
isset($_POST[$prfx . $el_name][$i]) &&
$_POST[$prfx . $el_name][$i]
!empty($data_array['mandatory']) &&
!empty($_POST[$prfx . $el_name][$i])
) {
$mand_okay = 1;
$row_okay[$i] = 1;
} elseif (
!empty($data_array['type']) && $data_array['type'] == 'radio_group' &&
!empty($data_array['type']) &&
$data_array['type'] == 'radio_group' &&
!isset($_POST[$prfx . $el_name])
) {
// radio group and set where one not active
@@ -1565,20 +1615,22 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$row_okay[$_POST[$prfx . $el_name][$i] ?? 0] = 0;
$default_wrong[$_POST[$prfx . $el_name][$i] ?? 0] = 1;
$error[$_POST[$prfx . $el_name][$i] ?? 0] = 1;
} elseif (isset($_POST[$prfx . $el_name][$i]) && !isset($error[$i])) {
} elseif (
isset($_POST[$prfx . $el_name][$i]) &&
!isset($error[$i])
) {
// $this->log->debug('edit_error_chk', '[$i]');
$element_set[$i] = 1;
$row_okay[$i] = 1;
} elseif (
isset($data_array['mandatory']) &&
$data_array['mandatory'] &&
!empty($data_array['mandatory']) &&
!$_POST[$prfx . $el_name][$i]
) {
$row_okay[$i] = 0;
}
// do optional error checks like for normal fields
// currently active: unique/alphanumeric
if (isset($data_array['error_check'])) {
if (!empty($data_array['error_check'])) {
foreach (explode('|', $data_array['error_check']) as $error_check) {
switch ($error_check) {
// check unique, check if field is filled and not same in _POST set
@@ -1597,6 +1649,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$reference_array['output_name'],
$i
);
$_POST['ERROR'][$prfx][$i] = 1;
}
break;
case 'alphanumericspace':
@@ -1612,6 +1665,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
$reference_array['output_name'],
$i
);
$_POST['ERROR'][$prfx][$i] = 1;
}
break;
}
@@ -1623,8 +1677,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
// main mandatory is met -> error msg
if (
!$mand_okay &&
isset($reference_array['mandatory']) &&
$reference_array['mandatory']
!empty($reference_array['mandatory'])
) {
$this->msg .= sprintf(
$this->l->__('You need to enter at least one data set for field <b>%s</b>!<br>'),
@@ -2533,12 +2586,13 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
}
// $this->log->debug('CFG QUERY', 'Q: ' . $q);
// only run if we have query strnig
$written_pos = [];
if (isset($q)) {
$prfx = $data['prefix']; // short
$pos = 0; // position in while for overwrite if needed
// read out the list and add the selected data if needed
while (is_array($res = $this->dbReturn($q))) {
$_data = [];
$prfx = $data['prefix']; // short
// go through each res
for ($i = 0, $i_max = count($q_select); $i < $i_max; $i++) {
// query select part, set to the element name
@@ -2568,13 +2622,48 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
}
$data['content'][] = $_data;
$data['pos'][] = [0 => $pos]; // this is for the checkboxes
$written_pos[] = $pos;
$pos++; // move up one
// reset and unset before next run
unset($_data);
}
}
// add lost error ones
$this->log->debug('ERROR', 'P: ' . $data['prefix'] . ', '
. $this->log->prAr($_POST['ERROR'][$data['prefix']] ?? []));
if ($this->error && !empty($_POST['ERROR'][$data['prefix']])) {
$prfx = $data['prefix']; // short
$_post_data = [];
// MAX entries defined via $data['pk_name'] entry (must exist)
$_max_pos = count($_POST[$data['pk_name']] ?? []);
// write all excte previous loaded @ $pos
foreach ($q_select as $_el_name) {
for ($_pos = 0; $_pos <= $_max_pos; $_pos++) {
// if not in data pos
if (!in_array($_pos, $written_pos)) {
$_post_data[$_pos][$prfx . $_el_name] =
$_POST[$prfx . $_el_name][$_pos] ?? '';
}
}
}
// only add if all fields in data are filled, else skip
// pk_name field is excluded of check
foreach ($_post_data as $_pos => $_data) {
$filled = false;
foreach ($_data as $_name => $_value) {
if ($_name != $data['pk_name'] && !empty($_value)) {
$filled = true;
}
}
if ($filled == true) {
$data['content'][] = $_data;
$data['pos'][] = [0 => $_pos];
}
}
}
// if this is normal single reference data check the content on the element count
// if there is a max_empty is set, then fill up new elements (unfilled) until we reach max empty
// if there is a max_empty is set, then fill up new elements (unfilled)
// until we reach max empty
if (
/*isset($this->element_list[$table_name]['type']) &&
$this->element_list[$table_name]['type'] == 'reference_data' &&*/

View File

@@ -0,0 +1,140 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditAccess implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_access_id' => [
'value' => $_POST['edit_access_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Access Group Name',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumericspace|unique'
],
'description' => [
'value' => $_POST['description'] ?? '',
'output_name' => 'Description',
'type' => 'textarea'
],
'color' => [
'value' => $_POST['color'] ?? '',
'output_name' => 'Color',
'mandatory' => 0,
'type' => 'text',
'size' => 10,
'length' => 9,
'error_check' => 'custom',
// FIXME: update regex check for hex/rgb/hsl with color check class
'error_regex' => '/^#([\dA-Fa-f]{6}|[\dA-Fa-f]{8})$/',
'error_example' => '#F6A544'
],
'enabled' => [
'value' => $_POST['enabled'] ?? 0,
'output_name' => 'Enabled',
'type' => 'binary',
'int' => 1, // OR 'bool' => 1
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'protected' => [
'value' => $_POST['protected'] ?? 0,
'output_name' => 'Protected',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'additional_acl' => [
'value' => $_POST['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",
'show_fields' => [
[
'name' => 'name'
],
],
'element_list' => [
'edit_access_data' => [
'output_name' => 'Edit Access Data',
'delete_name' => 'remove_edit_access_data',
// is not a sub table read and connect, but only a sub table with data
// 'type' => 'reference_data',
// maxium visible if no data is set, if filled add this number to visible
'max_empty' => 5,
'prefix' => 'ead',
'elements' => [
'name' => [
'type' => 'text',
'error_check' => 'alphanumeric|unique',
'output_name' => 'Name',
'mandatory' => 1
],
'value' => [
'type' => 'text',
'output_name' => 'Value'
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1]
],
/*'edit_access_id' => [
'int' => 1,
'type' => 'hidden',
// reference main key from master table above
'fk_id' => 1
],*/
'edit_access_data_id' => [
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
],
],
],
];
}
}
// __END__

View File

@@ -0,0 +1,137 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditGroups implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_group_id' => [
'value' => $_POST['edit_group_id'] ?? '',
'pk' => 1,
'type' => 'hidden'
],
'enabled' => [
'value' => $_POST['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Group Name',
'type' => 'text',
'mandatory' => 1
],
'edit_access_right_id' => [
'value' => $_POST['edit_access_right_id'] ?? '',
'output_name' => 'Group Level',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_scheme_id' => [
'value' => $_POST['edit_scheme_id'] ?? '',
'output_name' => 'Group Scheme',
'int_null' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_scheme_id, name FROM edit_scheme WHERE enabled = 1 ORDER BY name"
],
'additional_acl' => [
'value' => $_POST['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',
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'Enabled: '
],
],
'element_list' => [
'edit_page_access' => [
'output_name' => 'Pages',
'mandatory' => 1,
'delete' => 0, // set then reference entries are deleted, else the 'enable' flag is only set
'enable_name' => 'enable_page_access',
'prefix' => 'epa',
'read_data' => [
'table_name' => 'edit_page',
'pk_id' => 'edit_page_id',
'name' => 'name',
'order' => 'order_number'
],
'elements' => [
'edit_page_access_id' => [
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'int' => 1,
'preset' => 1, // first of the select
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_page_id' => [
'int' => 1,
'type' => 'hidden'
],
/*,
'edit_default' => [
'output_name' => 'Default',
'type' => 'radio',
'mandatory' => 1
],*/
],
], // edit pages ggroup
],
];
}
}
// __END__

View File

@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditLanguages implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_language_id' => [
'value' => $_POST['edit_language_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'short_name' => [
'value' => $_POST['short_name'] ?? '',
'output_name' => 'Language (short)',
'mandatory' => 1,
'type' => 'text',
'size' => 2,
'length' => 2
],
'long_name' => [
'value' => $_POST['long_name'] ?? '',
'output_name' => 'Language (long)',
'mandatory' => 1,
'type' => 'text',
'size' => 40
],
'iso_name' => [
'value' => $_POST['iso_name'] ?? '',
'output_name' => 'ISO Code',
'mandatory' => 1,
'type' => 'text'
],
'order_number' => [
'value' => $_POST['order_number'] ?? '',
'int' => 1,
'order' => 1
],
'enabled' => [
'value' => $_POST['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'lang_default' => [
'value' => $_POST['lang_default'] ?? '',
'output_name' => 'Default Language',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
],
'load_query' => "SELECT edit_language_id, long_name, iso_name, enabled "
. "FROM edit_language "
. "ORDER BY long_name",
'show_fields' => [
[
'name' => 'long_name'
],
[
'name' => 'iso_name',
'before_value' => 'ISO: '
],
[
'name' => 'enabled',
'before_value' => 'Enabled: ',
'binary' => ['Yes','No'],
],
],
'table_name' => 'edit_language'
];
}
}
// __END__

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditMenuGroup implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_menu_group_id' => [
'value' => $_POST['edit_menu_group_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Group name',
'mandatory' => 1,
'type' => 'text'
],
'flag' => [
'value' => $_POST['flag'] ?? '',
'output_name' => 'Flag',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumeric|unique'
],
'order_number' => [
'value' => $_POST['order_number'] ?? '',
'output_name' => 'Group order',
'type' => 'order',
'int' => 1,
'order' => 1
],
],
'table_name' => 'edit_menu_group',
'load_query' => "SELECT edit_menu_group_id, name FROM edit_menu_group ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
],
];
}
}
// __END__

View File

@@ -0,0 +1,275 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditPages implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_page_id' => [
'value' => $_POST['edit_page_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'filename' => [
'value' => $_POST['filename'] ?? '',
'output_name' => 'Add File ...',
'mandatory' => 1,
'type' => 'drop_down_db',
'query' => "SELECT DISTINCT temp_files.filename AS id, "
. "temp_files.folder || temp_files.filename AS name "
. "FROM temp_files "
. "LEFT JOIN edit_page ep ON temp_files.filename = ep.filename "
. "WHERE ep.filename IS NULL"
],
'hostname' => [
'value' => $_POST['hostname'] ?? '',
'output_name' => 'Hostname or folder',
'type' => 'text'
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Page name',
'mandatory' => 1,
'type' => 'text'
],
'order_number' => [
'value' => $_POST['order_number'] ?? '',
'output_name' => 'Page order',
'type' => 'order',
'int' => 1,
'order' => 1
],
/* 'flag' => [
'value' => $_POST['flag']) ?? '',
'output_name' => 'Page Flag',
'type' => 'drop_down_array',
'query' => [
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4',
'5' => '5'
],
],*/
'online' => [
'value' => $_POST['online'] ?? '',
'output_name' => 'Online',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'menu' => [
'value' => $_POST['menu'] ?? '',
'output_name' => 'Menu',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'popup' => [
'value' => $_POST['popup'] ?? '',
'output_name' => 'Popup',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'popup_x' => [
'value' => $_POST['popup_x'] ?? '',
'output_name' => 'Popup Width',
'int_null' => 1,
'type' => 'text',
'size' => 4,
'length' => 4
],
'popup_y' => [
'value' => $_POST['popup_y'] ?? '',
'output_name' => 'Popup Height',
'int_null' => 1,
'type' => 'text',
'size' => 4,
'length' => 4
],
'content_alias_edit_page_id' => [
'value' => $_POST['content_alias_edit_page_id'] ?? '',
'output_name' => 'Content Alias Source',
'int_null' => 1,
'type' => 'drop_down_db',
// query creation
'select_distinct' => 0,
'pk_name' => 'edit_page_id AS content_alias_edit_page_id',
'input_name' => 'name',
'table_name' => 'edit_page',
'where_not_self' => 1,
'order_by' => 'order_number'
// 'query' => "SELECT edit_page_id AS content_alias_edit_page_id, name ".
// "FROM edit_page ".
// (!empty($_POST['edit_page_id']) ? " WHERE edit_page_id <> ".$_POST['edit_page_id'] : "")." ".
// "ORDER BY order_number"
],
],
'load_query' => "SELECT edit_page_id, "
. "CASE WHEN hostname IS NOT NULL THEN hostname ELSE ''::VARCHAR END || filename AS filename, "
. "name, online, menu, popup "
. "FROM edit_page "
. "ORDER BY order_number",
'table_name' => 'edit_page',
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'filename',
'before_value' => 'Filename: '
],
[
'name' => 'online',
'binary' => ['Yes', 'No'],
'before_value' => 'Online: '
],
[
'name' => 'menu',
'binary' => ['Yes', 'No'],
'before_value' => 'Menu: '
],
[
'name' => 'popup',
'binary' => ['Yes', 'No'],
'before_value' => 'Popup: '
],
],
'reference_arrays' => [
'edit_visible_group' => [
'table_name' => 'edit_page_visible_group',
'other_table_pk' => 'edit_visible_group_id',
'output_name' => 'Visible Groups (access)',
'mandatory' => 1,
'select_size' => 10,
'selected' => $_POST['edit_visible_group_id'] ?? '',
'query' => "SELECT edit_visible_group_id, 'Name: ' || name || ', ' || 'Flag: ' || flag "
. "FROM edit_visible_group ORDER BY name"
],
'edit_menu_group' => [
'table_name' => 'edit_page_menu_group',
'other_table_pk' => 'edit_menu_group_id',
'output_name' => 'Menu Groups (grouping)',
'mandatory' => 1,
'select_size' => 10,
'selected' => $_POST['edit_menu_group_id'] ?? '',
'query' => "SELECT edit_menu_group_id, 'Name: ' || name || ', ' || 'Flag: ' || flag "
. "FROM edit_menu_group ORDER BY order_number"
],
],
'element_list' => [
'edit_query_string' => [
'output_name' => 'Query Strings',
'delete_name' => 'remove_query_string',
'prefix' => 'eqs',
'elements' => [
'name' => [
'output_name' => 'Name',
'type' => 'text',
'error_check' => 'unique|alphanumeric',
'mandatory' => 1
],
'value' => [
'output_name' => 'Value',
'type' => 'text'
],
'enabled' => [
'output_name' => 'Enabled',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'dynamic' => [
'output_name' => 'Dynamic',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'edit_query_string_id' => [
'type' => 'hidden',
'pk_id' => 1
],
], // elements
], // query_string element list
'edit_page_content' => [
'output_name' => 'Page Content',
'delete_name' => 'remove_page_content',
'prefix' => 'epc',
'elements' => [
'name' => [
'output_name' => 'Content',
'type' => 'text',
'error_check' => 'alphanumeric',
'mandatory' => 1
],
'uid' => [
'output_name' => 'UID',
'type' => 'text',
'error_check' => 'unique|alphanumeric',
'mandatory' => 1
],
'order_number' => [
'output_name' => 'Order',
'type' => 'text',
'error_check' => 'int',
'mandatory' => 1
],
'online' => [
'output_name' => 'Online',
'int' => 1,
'type' => 'checkbox',
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'int' => 1,
'preset' => 1, // first of the select
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_page_content_id' => [
'type' => 'hidden',
'pk_id' => 1
],
],
],
], // element list
];
}
}
// __END__

View File

@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditSchemas implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_scheme_id' => [
'value' => $_POST['edit_scheme_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Scheme Name',
'mandatory' => 1,
'type' => 'text'
],
'header_color' => [
'value' => $_POST['header_color'] ?? '',
'output_name' => 'Header Color',
'mandatory' => 1,
'type' => 'text',
'size' => 10,
'length' => 9,
'error_check' => 'custom',
// FIXME: update regex check for hex/rgb/hsl with color check class
'error_regex' => '/^#([\dA-Fa-f]{6}|[\dA-Fa-f]{8})$/',
'error_example' => '#F6A544'
],
'enabled' => [
'value' => $_POST['enabled'] ?? '',
'output_name' => 'Enabled',
'int' => 1,
'type' => 'binary',
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
],
'template' => [
'value' => $_POST['template'] ?? '',
'output_name' => 'Template',
'type' => 'text'
],
],
'table_name' => 'edit_scheme',
'load_query' => "SELECT edit_scheme_id, name, enabled FROM edit_scheme ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'Enabled: '
],
],
];
}
}
// __END__

View File

@@ -0,0 +1,456 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditUsers implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_user_id' => [
'value' => $_POST['edit_user_id'] ?? '',
'type' => 'hidden',
'pk' => 1,
'int' => 1
],
'username' => [
'value' => $_POST['username'] ?? '',
'output_name' => 'Username',
'mandatory' => 1,
'error_check' => 'unique|alphanumericextended',
'type' => 'text',
// if not min_edit_acl only read
// if not min_show_acl not visible
'min_edit_acl' => '100',
'min_show_acl' => '-1',
],
'password' => [
'value' => $_POST['password'] ?? '',
'HIDDEN_value' => $_POST['HIDDEN_password'] ?? '',
'CONFIRM_value' => $_POST['CONFIRM_password'] ?? '',
'output_name' => 'Password',
'mandatory' => 1,
'type' => 'password', // later has to be password for encryption in database
'update' => [ // connected field updates, and update data
'password_change_date' => [ // db row to update
'type' => 'date', // type of field (int/text/date/etc)
'value' => 'NOW()' // value [todo: complex reference
],
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
// password date when first insert and password is set, needs special field with connection to password
// password reset force interval, if set, user needs to reset password after X time period
'password_change_interval' => [
'value' => $_POST['password_change_interval'] ?? '',
'output_name' => 'Password change interval',
// can be any date length format. n Y/M/D [not H/M/S], only one set, no combination
'error_check' => 'intervalshort',
'type' => 'text',
'interval' => 1, // interval needs NULL write for empty
'size' => 5, // make it 5 chars long
'length' => 5,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'enabled' => [
'value' => $_POST['enabled'] ?? '',
'output_name' => 'Enabled',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '-1',
],
'deleted' => [
'value' => $_POST['deleted'] ?? '',
'output_name' => 'Deleted',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'strict' => [
'value' => $_POST['strict'] ?? '',
'output_name' => 'Strict (Lock after errors)',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'locked' => [
'value' => $_POST['locked'] ?? '',
'output_name' => 'Locked (auto set if strict with errors)',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'admin' => [
'value' => $_POST['admin'] ?? '',
'output_name' => 'Admin',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'debug' => [
'value' => $_POST['debug'] ?? '',
'output_name' => 'Debug',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'db_debug' => [
'value' => $_POST['db_debug'] ?? '',
'output_name' => 'DB Debug',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'email' => [
'value' => $_POST['email'] ?? '',
'output_name' => 'E-Mail',
'type' => 'text',
'error_check' => 'email',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'last_name' => [
'value' => $_POST['last_name'] ?? '',
'output_name' => 'Last Name',
'type' => 'text',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'first_name' => [
'value' => $_POST['first_name'] ?? '',
'output_name' => 'First Name',
'type' => 'text',
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'lock_until' => [
'value' => $_POST['lock_until'] ?? '',
'output_name' => 'Lock account until',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'lock_after' => [
'value' => $_POST['lock_after'] ?? '',
'output_name' => 'Lock account after',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id' => [
'value' => $_POST['login_user_id'] ?? '',
'output_name' => '_GET/_POST loginUserId direct login ID',
'type' => 'text',
'error_check' => 'unique|custom',
'error_regex' => "/^[A-Za-z0-9]+$/",
'emptynull' => 1,'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_set_date' => [
'output_name' => 'loginUserId set date',
'value' => $_POST['login_user_id_set_date'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_user_id_last_revalidate' => [
'output_name' => 'loginUserId last revalidate date',
'value' => $_POST['login_user_id_last_revalidate'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_user_id_locked' => [
'value' => $_POST['login_user_id_locked'] ?? '',
'output_name' => 'loginUserId usage locked',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_revalidate_after' => [
'value' => $_POST['login_user_id_revalidate_after'] ?? '',
'output_name' => 'loginUserId, User must login after n days',
'type' => 'text',
'error_check' => 'intervalshort',
'interval' => 1, // interval needs NULL write for empty
'size' => 5, // make it 5 chars long
'length' => 5,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_valid_from' => [
'value' => $_POST['login_user_id_valid_from'] ?? '',
'output_name' => 'loginUserId valid from',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_user_id_valid_until' => [
'value' => $_POST['login_user_id_valid_until'] ?? '',
'output_name' => 'loginUserId valid until',
'type' => 'datetime',
'error_check' => 'datetime',
'sql_read' => 'YYYY-MM-DD HH24:MI',
'datetime' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_language_id' => [
'value' => $_POST['edit_language_id'] ?? '',
'output_name' => 'Language',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_language_id, long_name "
. "FROM edit_language "
. "WHERE enabled = 1"
. "ORDER BY order_number",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_scheme_id' => [
'value' => $_POST['edit_scheme_id'] ?? '',
'output_name' => 'Scheme',
'int_null' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_scheme_id, name FROM edit_scheme WHERE enabled = 1 ORDER BY name",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_group_id' => [
'value' => $_POST['edit_group_id'] ?? '',
'output_name' => 'Group',
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_group_id, name FROM edit_group WHERE enabled = 1 ORDER BY name",
'mandatory' => 1,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'edit_access_right_id' => [
'value' => $_POST['edit_access_right_id'] ?? '',
'output_name' => 'User Level',
'mandatory' => 1,
'int' => 1,
'type' => 'drop_down_db',
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level",
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'login_error_count' => [
'output_name' => 'Login error count',
'value' => $_POST['login_error_count'] ?? '',
'type' => 'view',
'empty' => '0',
'min_show_acl' => '100',
],
'login_error_date_last' => [
'output_name' => 'Last login error',
'value' => $_POST['login_error_date_liast'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'login_error_date_first' => [
'output_name' => 'First login error',
'value' => $_POST['login_error_date_first'] ?? '',
'type' => 'view',
'empty' => '-',
'min_show_acl' => '100',
],
'protected' => [
'value' => $_POST['protected'] ?? '',
'output_name' => 'Protected',
'type' => 'binary',
'int' => 1,
'element_list' => [
'1' => 'Yes',
'0' => 'No'
],
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
'additional_acl' => [
'value' => $_POST['additional_acl'] ?? '',
'output_name' => 'Additional ACL (as JSON)',
'type' => 'textarea',
'error_check' => 'json',
'rows' => 10,
'cols' => 60,
'min_edit_acl' => '100',
'min_show_acl' => '100',
],
],
'load_query' => "SELECT edit_user_id, username, enabled, deleted, "
. "strict, locked, login_error_count "
. "FROM edit_user "
// if base acl is not 90 only list enabled
// if not admin flag, do not list admin flagged
. (
!$this->form->getAclAdmin() ?
"WHERE admin = 0 "
. (
!$this->form->checkBaseACL(90) ?
// $_POST['base_acl_level'] < 90 ?
"AND enabled = 1 " :
""
)
: ''
)
. "ORDER BY username",
'table_name' => 'edit_user',
'show_fields' => [
[
'name' => 'username'
],
[
'name' => 'enabled',
'binary' => ['Yes', 'No'],
'before_value' => 'ENBL: '
],
[
'name' => 'deleted',
'binary' => ['Yes', 'No'],
'before_value' => 'DEL: '
],
[
'name' => 'strict',
'binary' => ['Yes', 'No'],
'before_value' => 'STRC: '
],
[
'name' => 'locked',
'binary' => ['Yes', 'No'],
'before_value' => 'LCK: '
],
[
'name' => 'login_error_count',
'before_value' => 'ERR: '
],
],
'element_list' => [
'edit_access_user' => [
'output_name' => 'Accounts',
'mandatory' => 1,
// set then reference entries are deleted, else the 'enable' flag is only set
'delete' => 0,
// acl
'min_edit_acl' => '40',
'min_show_acl' => '20',
// table read prefix
'prefix' => 'ecu',
'read_data' => [
'table_name' => 'edit_access',
'pk_id' => 'edit_access_id',
'name' => 'name',
'order' => 'name'
],
'elements' => [
'edit_access_user_id' => [
'output_name' => 'Activate',
'type' => 'hidden',
'int' => 1,
'pk_id' => 1
],
'enabled' => [
'type' => 'checkbox',
'output_name' => 'Activate',
'int' => 1,
'element_list' => [1],
],
'edit_access_right_id' => [
'type' => 'drop_down_db',
'output_name' => 'Access Level',
'preset' => 1, // first of the select
'int' => 1,
'query' => "SELECT edit_access_right_id, name FROM edit_access_right ORDER BY level"
],
'edit_default' => [
'type' => 'radio_group',
'output_name' => 'Default',
'int' => 1,
'element_list' => 'radio_group'
],
'edit_access_id' => [
'type' => 'hidden',
'int' => 1
],
],
], // edit pages ggroup
],
];
}
}
// __END__

View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form\TableArrays;
class EditVisibleGroup implements \CoreLibs\Output\Form\TableArraysInterface
{
/** @var \CoreLibs\Output\Form\Generate */
private $form;
/**
* constructor
* @param \CoreLibs\Output\Form\Generate $form base form class
*/
public function __construct(\CoreLibs\Output\Form\Generate $form)
{
$this->form = $form;
$this->form->log->debug('CLASS LOAD', __NAMESPACE__ . __CLASS__);
}
/**
* return the table array
*
* @return array<mixed>
*/
public function setTableArray(): array
{
return [
'table_array' => [
'edit_visible_group_id' => [
'value' => $_POST['edit_visible_group_id'] ?? '',
'type' => 'hidden',
'pk' => 1
],
'name' => [
'value' => $_POST['name'] ?? '',
'output_name' => 'Group name',
'mandatory' => 1,
'type' => 'text'
],
'flag' => [
'value' => $_POST['flag'] ?? '',
'output_name' => 'Flag',
'mandatory' => 1,
'type' => 'text',
'error_check' => 'alphanumeric|unique'
],
],
'table_name' => 'edit_visible_group',
'load_query' => "SELECT edit_visible_group_id, name FROM edit_visible_group ORDER BY name",
'show_fields' => [
[
'name' => 'name'
],
],
];
}
}
// __END__

View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace CoreLibs\Output\Form;
interface TableArraysInterface
{
/**
* setTableArray interface, set the table array
* @return array<mixed>
*/
public function setTableArray(): array;
}
// __END__

View File

@@ -1 +1 @@
smarty-4.1.0/libs/
smarty-4.3.0/libs/

View File

@@ -1,77 +0,0 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
on:
- pull_request
- push
name: CI
jobs:
tests:
name: Tests
runs-on: ${{ matrix.os }}
env:
PHP_EXTENSIONS: dom, json, libxml, mbstring, pdo_sqlite, soap, xml, xmlwriter
PHP_INI_VALUES: assert.exception=1, zend.assertions=1
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
php-version:
- "7.1"
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
compiler:
- default
include:
- os: ubuntu-latest
php-version: "8.0"
compiler: jit
- os: ubuntu-latest
php-version: "8.1"
compiler: jit
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Override PHP ini values for JIT compiler
if: matrix.compiler == 'jit'
run: echo "PHP_INI_VALUES::assert.exception=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=1, opcache.optimization_level=-1, opcache.jit=1255, opcache.jit_buffer_size=32M" >> $GITHUB_ENV
- name: Install PHP with extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: pcov
extensions: ${{ env.PHP_EXTENSIONS }}
ini-values: ${{ env.PHP_INI_VALUES }}
- name: Validate composer.json and composer.lock
run: composer validate
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php-version }}-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run tests with phpunit
run: ./phpunit.sh

File diff suppressed because it is too large Load Diff

View File

@@ -1,179 +0,0 @@
Smarty: the PHP compiling template engine
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License below for more details.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@@ -1,20 +0,0 @@
# Smarty template engine
Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.
![CI](https://github.com/smarty-php/smarty/workflows/CI/badge.svg)
## Documentation
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
## Requirements
Smarty can be run with PHP 7.1 to PHP 8.1.
## Installation
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
To get the latest stable version of Smarty use:
```bash
composer require smarty/smarty
````
More in the [Getting Started](./docs/getting-started.md) section of the docs.

View File

@@ -1,19 +0,0 @@
# Security Policy
## Supported Versions
Smarty currently supports the latest minor version of Smarty 3 and Smarty 4. (Smarty 4 has not been released yet.)
| Version | Supported |
| ------- | ------------------ |
| 4.0.x | :white_check_mark: |
| 3.1.x | :white_check_mark: |
| < 3.1 | :x: |
## Reporting a Vulnerability
If you have discovered a security issue with Smarty, please contact us at mail [at] simonwisselink.nl. Do not
disclose your findings publicly and PLEASE PLEASE do not file an Issue.
We will try to confirm the vulnerability and develop a fix if appropriate. When we release the fix, we will publish
a security release. Please let us know if you want to be credited.

View File

@@ -1,49 +0,0 @@
{
"name": "smarty/smarty",
"type": "library",
"description": "Smarty - the compiling PHP template engine",
"keywords": [
"templating"
],
"homepage": "https://smarty-php.github.io/smarty/",
"license": "LGPL-3.0",
"authors": [
{
"name": "Monte Ohrt",
"email": "monte@ohrt.com"
},
{
"name": "Uwe Tews",
"email": "uwe.tews@googlemail.com"
},
{
"name": "Rodney Rehm",
"email": "rodney.rehm@medialize.de"
},
{
"name": "Simon Wisselink",
"homepage": "https://www.iwink.nl/"
}
],
"support": {
"issues": "https://github.com/smarty-php/smarty/issues",
"forum": "https://github.com/smarty-php/smarty/discussions"
},
"require": {
"php": "^7.1 || ^8.0"
},
"autoload": {
"classmap": [
"libs/"
]
},
"extra": {
"branch-alias": {
"dev-master": "4.0.x-dev"
}
},
"require-dev": {
"phpunit/phpunit": "^8.5 || ^7.5",
"smarty/smarty-lexer": "^3.1"
}
}

View File

@@ -1,5 +0,0 @@
title = Welcome to Smarty!
cutoff_size = 40
[setup]
bold = true

View File

@@ -1,35 +0,0 @@
<?php
/**
* Example Application
*
* @package Example-application
*/
require '../libs/Smarty.class.php';
$smarty = new Smarty;
//$smarty->force_compile = true;
$smarty->debugging = true;
$smarty->caching = true;
$smarty->cache_lifetime = 120;
$smarty->assign("Name", "Fred Irving Johnathan Bradley Peppergill", true);
$smarty->assign("FirstName", array("John", "Mary", "James", "Henry"));
$smarty->assign("LastName", array("Doe", "Smith", "Johnson", "Case"));
$smarty->assign(
"Class",
array(
array("A", "B", "C", "D"),
array("E", "F", "G", "H"),
array("I", "J", "K", "L"),
array("M", "N", "O", "P")
)
);
$smarty->assign(
"contacts",
array(
array("phone" => "1", "fax" => "2", "cell" => "3"),
array("phone" => "555-4444", "fax" => "555-3333", "cell" => "760-1234")
)
);
$smarty->assign("option_values", array("NY", "NE", "KS", "IA", "OK", "TX"));
$smarty->assign("option_output", array("New York", "Nebraska", "Kansas", "Iowa", "Oklahoma", "Texas"));
$smarty->assign("option_selected", "NE");
$smarty->display('index.tpl');

View File

@@ -1,85 +0,0 @@
<?php
/**
* APC CacheResource
* CacheResource Implementation based on the KeyValueStore API to use
* memcache as the storage resource for Smarty's output caching.
* *
*
* @package CacheResource-examples
* @author Uwe Tews
*/
class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore
{
/**
* Smarty_CacheResource_Apc constructor.
*
* @throws \Exception
*/
public function __construct()
{
// test if APC is present
if (!function_exists('apc_cache_info')) {
throw new Exception('APC Template Caching Error: APC is not installed');
}
}
/**
* Read values for a set of keys from cache
*
* @param array $keys list of keys to fetch
*
* @return array list of values with the given keys used as indexes
* @return boolean true on success, false on failure
*/
protected function read(array $keys)
{
$_res = array();
$res = apc_fetch($keys);
foreach ($res as $k => $v) {
$_res[ $k ] = $v;
}
return $_res;
}
/**
* Save values for a set of keys to cache
*
* @param array $keys list of values to save
* @param int $expire expiration time
*
* @return boolean true on success, false on failure
*/
protected function write(array $keys, $expire = null)
{
foreach ($keys as $k => $v) {
apc_store($k, $v, $expire);
}
return true;
}
/**
* Remove values from cache
*
* @param array $keys list of keys to delete
*
* @return boolean true on success, false on failure
*/
protected function delete(array $keys)
{
foreach ($keys as $k) {
apc_delete($k);
}
return true;
}
/**
* Remove *all* values from cache
*
* @return boolean true on success, false on failure
*/
protected function purge()
{
return apc_clear_cache('user');
}
}

View File

@@ -1,99 +0,0 @@
<?php
/**
* Memcache CacheResource
* CacheResource Implementation based on the KeyValueStore API to use
* memcache as the storage resource for Smarty's output caching.
* Note that memcache has a limitation of 256 characters per cache-key.
* To avoid complications all cache-keys are translated to a sha1 hash.
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore
{
/**
* memcache instance
*
* @var Memcache
*/
protected $memcache = null;
/**
* Smarty_CacheResource_Memcache constructor.
*/
public function __construct()
{
if (class_exists('Memcached')) {
$this->memcache = new Memcached();
} else {
$this->memcache = new Memcache();
}
$this->memcache->addServer('127.0.0.1', 11211);
}
/**
* Read values for a set of keys from cache
*
* @param array $keys list of keys to fetch
*
* @return array list of values with the given keys used as indexes
* @return boolean true on success, false on failure
*/
protected function read(array $keys)
{
$res = array();
foreach ($keys as $key) {
$k = sha1($key);
$res[$key] = $this->memcache->get($k);
}
return $res;
}
/**
* Save values for a set of keys to cache
*
* @param array $keys list of values to save
* @param int $expire expiration time
*
* @return boolean true on success, false on failure
*/
protected function write(array $keys, $expire = null)
{
foreach ($keys as $k => $v) {
$k = sha1($k);
if (class_exists('Memcached')) {
$this->memcache->set($k, $v, $expire);
} else {
$this->memcache->set($k, $v, 0, $expire);
}
}
return true;
}
/**
* Remove values from cache
*
* @param array $keys list of keys to delete
*
* @return boolean true on success, false on failure
*/
protected function delete(array $keys)
{
foreach ($keys as $k) {
$k = sha1($k);
$this->memcache->delete($k);
}
return true;
}
/**
* Remove *all* values from cache
*
* @return boolean true on success, false on failure
*/
protected function purge()
{
return $this->memcache->flush();
}
}

View File

@@ -1,183 +0,0 @@
<?php
/**
* MySQL CacheResource
* CacheResource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's output caching.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `output_cache` (
* `id` CHAR(40) NOT NULL COMMENT 'sha1 hash',
* `name` VARCHAR(250) NOT NULL,
* `cache_id` VARCHAR(250) NULL DEFAULT NULL,
* `compile_id` VARCHAR(250) NULL DEFAULT NULL,
* `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
* `content` LONGTEXT NOT NULL,
* PRIMARY KEY (`id`),
* INDEX(`name`),
* INDEX(`cache_id`),
* INDEX(`compile_id`),
* INDEX(`modified`)
* ) ENGINE = InnoDB;</pre>
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom
{
/**
* @var \PDO
*/
protected $db;
/**
* @var \PDOStatement
*/
protected $fetch;
/**
* @var \PDOStatement
*/
protected $fetchTimestamp;
/**
* @var \PDOStatement
*/
protected $save;
/**
* Smarty_CacheResource_Mysql constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
$this->save = $this->db->prepare(
'REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
VALUES (:id, :name, :cache_id, :compile_id, :content)'
);
}
/**
* fetch cached content and its modification time from data source
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param string $content cached content
* @param integer $mtime cache modification timestamp (epoch)
*
* @return void
*/
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
{
$this->fetch->execute(array('id' => $id));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$content = $row[ 'content' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$content = null;
$mtime = null;
}
}
/**
* Fetch cached content's modification timestamp from data source
*
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than
* loading the complete cached content.
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
*
* @return integer|boolean timestamp (epoch) the template was modified, or false if not found
*/
protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
{
$this->fetchTimestamp->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestamp->fetchColumn());
$this->fetchTimestamp->closeCursor();
return $mtime;
}
/**
* Save content to cache
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer|null $exp_time seconds till expiration time in seconds or null
* @param string $content content to cache
*
* @return boolean success
*/
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
{
$this->save->execute(
array('id' => $id,
'name' => $name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'content' => $content,)
);
return !!$this->save->rowCount();
}
/**
* Delete content from cache
*
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer|null $exp_time seconds till expiration or null
*
* @return integer number of deleted caches
*/
protected function delete($name, $cache_id, $compile_id, $exp_time)
{
// delete the whole cache
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
// returning the number of deleted caches would require a second query to count them
$query = $this->db->query('TRUNCATE TABLE output_cache');
return -1;
}
// build the filter
$where = array();
// equal test name
if ($name !== null) {
$where[] = 'name = ' . $this->db->quote($name);
}
// equal test compile_id
if ($compile_id !== null) {
$where[] = 'compile_id = ' . $this->db->quote($compile_id);
}
// range test expiration time
if ($exp_time !== null) {
$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
}
// equal test cache_id and match sub-groups
if ($cache_id !== null) {
$where[] =
'(cache_id = ' .
$this->db->quote($cache_id) .
' OR cache_id LIKE ' .
$this->db->quote($cache_id . '|%') .
')';
}
// run delete query
$query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
return $query->rowCount();
}
}

View File

@@ -1,346 +0,0 @@
<?php
/**
* PDO Cache Handler
* Allows you to store Smarty Cache files into your db.
* Example table :
* CREATE TABLE `smarty_cache` (
* `id` char(40) NOT NULL COMMENT 'sha1 hash',
* `name` varchar(250) NOT NULL,
* `cache_id` varchar(250) DEFAULT NULL,
* `compile_id` varchar(250) DEFAULT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
* `expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
* `content` mediumblob NOT NULL,
* PRIMARY KEY (`id`),
* KEY `name` (`name`),
* KEY `cache_id` (`cache_id`),
* KEY `compile_id` (`compile_id`),
* KEY `modified` (`modified`),
* KEY `expire` (`expire`)
* ) ENGINE=InnoDB
* Example usage :
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
* $smarty->setCachingType('pdo');
* $smarty->loadPlugin('Smarty_CacheResource_Pdo');
* $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache'));
*
* @author Beno!t POLASZEK - 2014
*/
class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
{
/**
* @var string[]
*/
protected $fetchStatements = array('default' => 'SELECT %2$s
FROM %1$s
WHERE 1
AND id = :id
AND cache_id IS NULL
AND compile_id IS NULL',
'withCacheId' => 'SELECT %2$s
FROM %1$s
WHERE 1
AND id = :id
AND cache_id = :cache_id
AND compile_id IS NULL',
'withCompileId' => 'SELECT %2$s
FROM %1$s
WHERE 1
AND id = :id
AND compile_id = :compile_id
AND cache_id IS NULL',
'withCacheIdAndCompileId' => 'SELECT %2$s
FROM %1$s
WHERE 1
AND id = :id
AND cache_id = :cache_id
AND compile_id = :compile_id');
/**
* @var string
*/
protected $insertStatement = 'INSERT INTO %s
SET id = :id,
name = :name,
cache_id = :cache_id,
compile_id = :compile_id,
modified = CURRENT_TIMESTAMP,
expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),
content = :content
ON DUPLICATE KEY UPDATE
name = :name,
cache_id = :cache_id,
compile_id = :compile_id,
modified = CURRENT_TIMESTAMP,
expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),
content = :content';
/**
* @var string
*/
protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s';
/**
* @var string
*/
protected $truncateStatement = 'TRUNCATE TABLE %s';
/**
* @var string
*/
protected $fetchColumns = 'modified, content';
/**
* @var string
*/
protected $fetchTimestampColumns = 'modified';
/**
* @var \PDO
*/
protected $pdo;
/**
* @var
*/
protected $table;
/**
* @var null
*/
protected $database;
/**
* Constructor
*
* @param PDO $pdo PDO : active connection
* @param string $table : table (or view) name
* @param string $database : optional - if table is located in another db
*
* @throws \SmartyException
*/
public function __construct(PDO $pdo, $table, $database = null)
{
if (is_null($table)) {
throw new SmartyException("Table name for caching can't be null");
}
$this->pdo = $pdo;
$this->table = $table;
$this->database = $database;
$this->fillStatementsWithTableName();
}
/**
* Fills the table name into the statements.
*
* @return $this Current Instance
* @access protected
*/
protected function fillStatementsWithTableName()
{
foreach ($this->fetchStatements as &$statement) {
$statement = sprintf($statement, $this->getTableName(), '%s');
}
$this->insertStatement = sprintf($this->insertStatement, $this->getTableName());
$this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s');
$this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName());
return $this;
}
/**
* Gets the fetch statement, depending on what you specify
*
* @param string $columns : the column(s) name(s) you want to retrieve from the database
* @param string $id unique cache content identifier
* @param string|null $cache_id cache id
* @param string|null $compile_id compile id
*
* @access protected
* @return \PDOStatement
*/
protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null)
{
$args = array();
if (!is_null($cache_id) && !is_null($compile_id)) {
$query = $this->fetchStatements[ 'withCacheIdAndCompileId' ] and
$args = array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id);
} elseif (is_null($cache_id) && !is_null($compile_id)) {
$query = $this->fetchStatements[ 'withCompileId' ] and
$args = array('id' => $id, 'compile_id' => $compile_id);
} elseif (!is_null($cache_id) && is_null($compile_id)) {
$query = $this->fetchStatements[ 'withCacheId' ] and $args = array('id' => $id, 'cache_id' => $cache_id);
} else {
$query = $this->fetchStatements[ 'default' ] and $args = array('id' => $id);
}
$query = sprintf($query, $columns);
$stmt = $this->pdo->prepare($query);
foreach ($args as $key => $value) {
$stmt->bindValue($key, $value);
}
return $stmt;
}
/**
* fetch cached content and its modification time from data source
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string|null $cache_id cache id
* @param string|null $compile_id compile id
* @param string $content cached content
* @param integer $mtime cache modification timestamp (epoch)
*
* @return void
* @access protected
*/
protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime)
{
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
$stmt->execute();
$row = $stmt->fetch();
$stmt->closeCursor();
if ($row) {
$content = $this->outputContent($row[ 'content' ]);
$mtime = strtotime($row[ 'modified' ]);
} else {
$content = null;
$mtime = null;
}
}
/**
* Fetch cached content's modification timestamp from data source
* {@internal implementing this method is optional.
* Only implement it if modification times can be accessed faster than loading the complete cached content.}}
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string|null $cache_id cache id
* @param string|null $compile_id compile id
*
* @return integer|boolean timestamp (epoch) the template was modified, or false if not found
* @access protected
*/
// protected function fetchTimestamp($id, $name, $cache_id = null, $compile_id = null) {
// $stmt = $this->getFetchStatement($this->fetchTimestampColumns, $id, $cache_id, $compile_id);
// $stmt -> execute();
// $mtime = strtotime($stmt->fetchColumn());
// $stmt -> closeCursor();
// return $mtime;
// }
/**
* Save content to cache
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string|null $cache_id cache id
* @param string|null $compile_id compile id
* @param integer|null $exp_time seconds till expiration time in seconds or null
* @param string $content content to cache
*
* @return boolean success
* @access protected
*/
protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content)
{
$stmt = $this->pdo->prepare($this->insertStatement);
$stmt->bindValue('id', $id);
$stmt->bindValue('name', $name);
$stmt->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);
$stmt->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);
$stmt->bindValue('expire', (int)$exp_time, PDO::PARAM_INT);
$stmt->bindValue('content', $this->inputContent($content));
$stmt->execute();
return !!$stmt->rowCount();
}
/**
* Encodes the content before saving to database
*
* @param string $content
*
* @return string $content
* @access protected
*/
protected function inputContent($content)
{
return $content;
}
/**
* Decodes the content before saving to database
*
* @param string $content
*
* @return string $content
* @access protected
*/
protected function outputContent($content)
{
return $content;
}
/**
* Delete content from cache
*
* @param string|null $name template name
* @param string|null $cache_id cache id
* @param string|null $compile_id compile id
* @param integer|null|-1 $exp_time seconds till expiration or null
*
* @return integer number of deleted caches
* @access protected
*/
protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null)
{
// delete the whole cache
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
// returning the number of deleted caches would require a second query to count them
$this->pdo->query($this->truncateStatement);
return -1;
}
// build the filter
$where = array();
// equal test name
if ($name !== null) {
$where[] = 'name = ' . $this->pdo->quote($name);
}
// equal test cache_id and match sub-groups
if ($cache_id !== null) {
$where[] =
'(cache_id = ' .
$this->pdo->quote($cache_id) .
' OR cache_id LIKE ' .
$this->pdo->quote($cache_id . '|%') .
')';
}
// equal test compile_id
if ($compile_id !== null) {
$where[] = 'compile_id = ' . $this->pdo->quote($compile_id);
}
// for clearing expired caches
if ($exp_time === Smarty::CLEAR_EXPIRED) {
$where[] = 'expire < CURRENT_TIMESTAMP';
} // range test expiration time
elseif ($exp_time !== null) {
$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
}
// run delete query
$query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where)));
return $query->rowCount();
}
/**
* Gets the formatted table name
*
* @return string
* @access protected
*/
protected function getTableName()
{
return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`";
}
}

View File

@@ -1,42 +0,0 @@
<?php
require_once 'cacheresource.pdo.php';
/**
* PDO Cache Handler with GZIP support
* Example usage :
* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");
* $smarty->setCachingType('pdo_gzip');
* $smarty->loadPlugin('Smarty_CacheResource_Pdo_Gzip');
* $smarty->registerCacheResource('pdo_gzip', new Smarty_CacheResource_Pdo_Gzip($cnx, 'smarty_cache'));
*
* @require Smarty_CacheResource_Pdo class
* @author Beno!t POLASZEK - 2014
*/
class Smarty_CacheResource_Pdo_Gzip extends Smarty_CacheResource_Pdo
{
/**
* Encodes the content before saving to database
*
* @param string $content
*
* @return string $content
* @access protected
*/
protected function inputContent($content)
{
return gzdeflate($content);
}
/**
* Decodes the content before saving to database
*
* @param string $content
*
* @return string $content
* @access protected
*/
protected function outputContent($content)
{
return gzinflate($content);
}
}

View File

@@ -1,62 +0,0 @@
<?php
/**
* Extends All Resource
* Resource Implementation modifying the extends-Resource to walk
* through the template_dirs and inherit all templates of the same name
*
* @package Resource-examples
* @author Rodney Rehm
*/
class Smarty_Resource_Extendsall extends Smarty_Internal_Resource_Extends
{
/**
* populate Source Object with meta data from Resource
*
* @param Smarty_Template_Source $source source object
* @param Smarty_Internal_Template $_template template object
*
* @return void
*/
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$uid = '';
$sources = array();
$timestamp = 0;
foreach ($source->smarty->getTemplateDir() as $key => $directory) {
try {
$s = Smarty_Resource::source(null, $source->smarty, 'file:' . '[' . $key . ']' . $source->name);
if (!$s->exists) {
continue;
}
$sources[ $s->uid ] = $s;
$uid .= $s->filepath;
$timestamp = $s->timestamp > $timestamp ? $s->timestamp : $timestamp;
} catch (SmartyException $e) {
}
}
if (!$sources) {
$source->exists = false;
return;
}
$sources = array_reverse($sources, true);
reset($sources);
$s = current($sources);
$source->components = $sources;
$source->filepath = $s->filepath;
$source->uid = sha1($uid . $source->smarty->_joined_template_dir);
$source->exists = true;
$source->timestamp = $timestamp;
}
/**
* Disable timestamp checks for extendsall resource.
* The individual source components will be checked.
*
* @return bool false
*/
public function checkTimestamps()
{
return false;
}
}

View File

@@ -1,101 +0,0 @@
<?php
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class Smarty_Resource_Mysql extends Smarty_Resource_Custom
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* prepared fetchTimestamp() statement
*
* @var \PDOStatement
*/
protected $mtime;
/**
* Smarty_Resource_Mysql constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
/**
* Fetch a template's modification time from database
*
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than
* loading the comple template source.
*
* @param string $name template name
*
* @return integer timestamp (epoch) the template was modified
*/
protected function fetchTimestamp($name)
{
$this->mtime->execute(array('name' => $name));
$mtime = $this->mtime->fetchColumn();
$this->mtime->closeCursor();
return strtotime($mtime);
}
}

View File

@@ -1,77 +0,0 @@
<?php
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Note that this MySQL implementation fetches the source and timestamps in
* a single database query, instead of two separate like resource.mysql.php does.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class Smarty_Resource_Mysqls extends Smarty_Resource_Custom
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* Smarty_Resource_Mysqls constructor.
*
* @throws \SmartyException
*/
public function __construct()
{
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, source FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
}

View File

@@ -1,2 +0,0 @@
</BODY>
</HTML>

View File

@@ -1,5 +0,0 @@
<HTML>
<HEAD>
<TITLE>{$title} - {$Name}</TITLE>
</HEAD>
<BODY bgcolor="#ffffff">

View File

@@ -1,87 +0,0 @@
{config_load file="test.conf" section="setup"}
{include file="header.tpl" title=foo}
<PRE>
{* bold and title are read from the config file *}
{if #bold#}<b>{/if}
{* capitalize the first letters of each word of the title *}
Title: {#title#|capitalize}
{if #bold#}</b>{/if}
The current date and time is {$smarty.now|date_format:"%Y-%m-%d %H:%M:%S"}
The value of global assigned variable $SCRIPT_NAME is {$SCRIPT_NAME}
Example of accessing server environment variable SERVER_NAME: {$smarty.server.SERVER_NAME}
The value of {ldelim}$Name{rdelim} is <b>{$Name}</b>
variable modifier example of {ldelim}$Name|upper{rdelim}
<b>{$Name|upper}</b>
An example of a section loop:
{section name=outer
loop=$FirstName}
{if $smarty.section.outer.index is odd by 2}
{$smarty.section.outer.rownum} . {$FirstName[outer]} {$LastName[outer]}
{else}
{$smarty.section.outer.rownum} * {$FirstName[outer]} {$LastName[outer]}
{/if}
{sectionelse}
none
{/section}
An example of section looped key values:
{section name=sec1 loop=$contacts}
phone: {$contacts[sec1].phone}
<br>
fax: {$contacts[sec1].fax}
<br>
cell: {$contacts[sec1].cell}
<br>
{/section}
<p>
testing strip tags
{strip}
<table border=0>
<tr>
<td>
<A HREF="{$SCRIPT_NAME}">
<font color="red">This is a test </font>
</A>
</td>
</tr>
</table>
{/strip}
</PRE>
This is an example of the html_select_date function:
<form>
{html_select_date start_year=1998 end_year=2010}
</form>
This is an example of the html_select_time function:
<form>
{html_select_time use_24_hours=false}
</form>
This is an example of the html_options function:
<form>
<select name=states>
{html_options values=$option_values selected=$option_selected output=$option_output}
</select>
</form>
{include file="footer.tpl"}

View File

@@ -1 +0,0 @@
theme: jekyll-theme-minimal

View File

@@ -1,332 +0,0 @@
Tips & Tricks {#tips}
=============
Blank Variable Handling {#tips.blank.var.handling}
=======================
There may be times when you want to print a default value for an empty
variable instead of printing nothing, such as printing `&nbsp;` so that
html table backgrounds work properly. Many would use an
[`{if}`](#language.function.if) statement to handle this, but there is a
shorthand way with Smarty, using the
[`default`](#language.modifier.default) variable modifier.
> **Note**
>
> "Undefined variable" errors will show an E\_NOTICE if not disabled in
> PHP\'s [`error_reporting()`](&url.php-manual;error_reporting) level or
> Smarty\'s [`$error_reporting`](#variable.error.reporting) property and
> a variable had not been assigned to Smarty.
{* the long way *}
{if $title eq ''}
&nbsp;
{else}
{$title}
{/if}
{* the short way *}
{$title|default:'&nbsp;'}
See also [`default`](#language.modifier.default) modifier and [default
variable handling](#tips.default.var.handling).
Default Variable Handling {#tips.default.var.handling}
=========================
If a variable is used frequently throughout your templates, applying the
[`default`](#language.modifier.default) modifier every time it is
mentioned can get a bit ugly. You can remedy this by assigning the
variable its default value with the
[`{assign}`](#language.function.assign) function.
{* do this somewhere at the top of your template *}
{assign var='title' value=$title|default:'no title'}
{* if $title was empty, it now contains the value "no title" when you use it *}
{$title}
See also [`default`](#language.modifier.default) modifier and [blank
variable handling](#tips.blank.var.handling).
Passing variable title to header template {#tips.passing.vars}
=========================================
When the majority of your templates use the same headers and footers, it
is common to split those out into their own templates and
[`{include}`](#language.function.include) them. But what if the header
needs to have a different title, depending on what page you are coming
from? You can pass the title to the header as an
[attribute](#language.syntax.attributes) when it is included.
`mainpage.tpl` - When the main page is drawn, the title of "Main Page"
is passed to the `header.tpl`, and will subsequently be used as the
title.
{include file='header.tpl' title='Main Page'}
{* template body goes here *}
{include file='footer.tpl'}
`archives.tpl` - When the archives page is drawn, the title will be
"Archives". Notice in the archive example, we are using a variable from
the `archives_page.conf` file instead of a hard coded variable.
{config_load file='archive_page.conf'}
{include file='header.tpl' title=#archivePageTitle#}
{* template body goes here *}
{include file='footer.tpl'}
`header.tpl` - Notice that "Smarty News" is printed if the `$title`
variable is not set, using the [`default`](#language.modifier.default)
variable modifier.
<html>
<head>
<title>{$title|default:'Smarty News'}</title>
</head>
<body>
`footer.tpl`
</body>
</html>
Dates {#tips.dates}
=====
As a rule of thumb, always pass dates to Smarty as
[timestamps](&url.php-manual;time). This allows template designers to
use the [`date_format`](#language.modifier.date.format) modifier for
full control over date formatting, and also makes it easy to compare
dates if necessary.
{$startDate|date_format}
This will output:
Jan 4, 2009
{$startDate|date_format:"%Y/%m/%d"}
This will output:
2009/01/04
Dates can be compared in the template by timestamps with:
{if $order_date < $invoice_date}
...do something..
{/if}
When using [`{html_select_date}`](#language.function.html.select.date)
in a template, the programmer will most likely want to convert the
output from the form back into timestamp format. Here is a function to
help you with that.
<?php
// this assumes your form elements are named
// startDate_Day, startDate_Month, startDate_Year
$startDate = makeTimeStamp($startDate_Year, $startDate_Month, $startDate_Day);
function makeTimeStamp($year='', $month='', $day='')
{
if(empty($year)) {
$year = strftime('%Y');
}
if(empty($month)) {
$month = strftime('%m');
}
if(empty($day)) {
$day = strftime('%d');
}
return mktime(0, 0, 0, $month, $day, $year);
}
?>
See also [`{html_select_date}`](#language.function.html.select.date),
[`{html_select_time}`](#language.function.html.select.time),
[`date_format`](#language.modifier.date.format) and
[`$smarty.now`](#language.variables.smarty.now),
WAP/WML {#tips.wap}
=======
WAP/WML templates require a php [Content-Type
header](&url.php-manual;header) to be passed along with the template.
The easist way to do this would be to write a custom function that
prints the header. If you are using [caching](#caching), that won\'t
work so we\'ll do it using the [`{insert}`](#language.function.insert)
tag; remember `{insert}` tags are not cached! Be sure that there is
nothing output to the browser before the template, or else the header
may fail.
<?php
// be sure apache is configure for the .wml extensions!
// put this function somewhere in your application, or in Smarty.addons.php
function insert_header($params)
{
// this function expects $content argument
if (empty($params['content'])) {
return;
}
header($params['content']);
return;
}
?>
your Smarty template *must* begin with the insert tag :
{insert name=header content="Content-Type: text/vnd.wap.wml"}
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<!-- begin new wml deck -->
<wml>
<!-- begin first card -->
<card>
<do type="accept">
<go href="#two"/>
</do>
<p>
Welcome to WAP with Smarty!
Press OK to continue...
</p>
</card>
<!-- begin second card -->
<card id="two">
<p>
Pretty easy isn't it?
</p>
</card>
</wml>
Componentized Templates {#tips.componentized.templates}
=======================
Traditionally, programming templates into your applications goes as
follows: First, you accumulate your variables within your PHP
application, (maybe with database queries.) Then, you instantiate your
Smarty object, [`assign()`](#api.assign) the variables and
[`display()`](#api.display) the template. So lets say for example we
have a stock ticker on our template. We would collect the stock data in
our application, then assign these variables in the template and display
it. Now wouldn\'t it be nice if you could add this stock ticker to any
application by merely including the template, and not worry about
fetching the data up front?
You can do this by writing a custom plugin for fetching the content and
assigning it to a template variable.
`function.load_ticker.php` - drop file in
[`$plugins directory`](#variable.plugins.dir)
<?php
// setup our function for fetching stock data
function fetch_ticker($symbol)
{
// put logic here that fetches $ticker_info
// from some ticker resource
return $ticker_info;
}
function smarty_function_load_ticker($params, $smarty)
{
// call the function
$ticker_info = fetch_ticker($params['symbol']);
// assign template variable
$smarty->assign($params['assign'], $ticker_info);
}
?>
`index.tpl`
{load_ticker symbol='SMARTY' assign='ticker'}
Stock Name: {$ticker.name} Stock Price: {$ticker.price}
See also [`{include_php}`](#language.function.include.php),
[`{include}`](#language.function.include) and
[`{php}`](#language.function.php).
Obfuscating E-mail Addresses {#tips.obfuscating.email}
============================
Do you ever wonder how your email address gets on so many spam mailing
lists? One way spammers collect email addresses is from web pages. To
help combat this problem, you can make your email address show up in
scrambled javascript in the HTML source, yet it it will look and work
correctly in the browser. This is done with the
[`{mailto}`](#language.function.mailto) plugin.
<div id="contact">Send inquiries to
{mailto address=$EmailAddress encode='javascript' subject='Hello'}
</div>
> **Note**
>
> This method isn\'t 100% foolproof. A spammer could conceivably program
> his e-mail collector to decode these values, but not likely\....
> hopefully..yet \... wheres that quantum computer :-?.
See also [`escape`](#language.modifier.escape) modifier and
[`{mailto}`](#language.function.mailto).

View File

@@ -1,120 +0,0 @@
Troubleshooting
===============
Smarty/PHP errors {#smarty.php.errors}
=================
Smarty can catch many errors such as missing tag attributes or malformed
variable names. If this happens, you will see an error similar to the
following:
Warning: Smarty: [in index.tpl line 4]: syntax error: unknown tag - '%blah'
in /path/to/smarty/Smarty.class.php on line 1041
Fatal error: Smarty: [in index.tpl line 28]: syntax error: missing section name
in /path/to/smarty/Smarty.class.php on line 1041
Smarty shows you the template name, the line number and the error. After
that, the error consists of the actual line number in the Smarty class
that the error occurred.
There are certain errors that Smarty cannot catch, such as missing close
tags. These types of errors usually end up in PHP compile-time parsing
errors.
Parse error: parse error in /path/to/smarty/templates_c/index.tpl.php on line 75
When you encounter a PHP parsing error, the error line number will
correspond to the compiled PHP script, NOT the template itself. Usually
you can look at the template and spot the syntax error. Here are some
common things to look for: missing close tags for
[`{if}{/if}`](#language.function.if) or
[`{section}{/section}`](#language.function.if), or syntax of logic
within an `{if}` tag. If you can\'t find the error, you might have to
open the compiled PHP file and go to the line number to figure out where
the corresponding error is in the template.
Warning: Smarty error: unable to read resource: "index.tpl" in...
or
Warning: Smarty error: unable to read resource: "site.conf" in...
- The [`$template_dir`](#variable.template.dir) is incorrect, doesn\'t
exist or the file `index.tpl` is not in the `templates/` directory
- A [`{config_load}`](#language.function.config.load) function is
within a template (or [`configLoad()`](#api.config.load) has been
called) and either [`$config_dir`](#variable.config.dir) is
incorrect, does not exist or `site.conf` is not in the directory.
<!-- -->
Fatal error: Smarty error: the $compile_dir 'templates_c' does not exist,
or is not a directory...
- Either the [`$compile_dir`](#variable.compile.dir)is incorrectly
set, the directory does not exist, or `templates_c` is a file and
not a directory.
<!-- -->
Fatal error: Smarty error: unable to write to $compile_dir '....
- The [`$compile_dir`](#variable.compile.dir) is not writable by the
web server. See the bottom of the [installing
smarty](#installing.smarty.basic) page for more about permissions.
<!-- -->
Fatal error: Smarty error: the $cache_dir 'cache' does not exist,
or is not a directory. in /..
- This means that [`$caching`](#variable.caching) is enabled and
either; the [`$cache_dir`](#variable.cache.dir) is incorrectly set,
the directory does not exist, or `cache/` is a file and not a
directory.
<!-- -->
Fatal error: Smarty error: unable to write to $cache_dir '/...
- This means that [`$caching`](#variable.caching) is enabled and the
[`$cache_dir`](#variable.cache.dir) is not writable by the web
server. See the bottom of the [installing
smarty](#installing.smarty.basic) page for permissions.
<!-- -->
Warning: filemtime(): stat failed for /path/to/smarty/cache/3ab50a623e65185c49bf17c63c90cc56070ea85c.one.tpl.php
in /path/to/smarty/libs/sysplugins/smarty_resource.php
- This means that your application registered a custom error hander
(using [set\_error\_handler()](&url.php-manual;set_error_handler))
which is not respecting the given `$errno` as it should. If, for
whatever reason, this is the desired behaviour of your custom error
handler, please call
[`muteExpectedErrors()`](#api.mute.expected.errors) after you\'ve
registered your custom error handler.
See also [debugging](#chapter.debugging.console).

View File

@@ -1,41 +0,0 @@
Debugging Console {#chapter.debugging.console}
=================
There is a debugging console included with Smarty. The console informs
you of all the [included](./language-builtin-functions/language-function-include.md) templates,
[assigned](../programmers/api-functions/api-assign.md) variables and
[config](./language-variables/language-config-variables.md) file variables for the current
invocation of the template. A template file named `debug.tpl` is
included with the distribution of Smarty which controls the formatting
of the console.
Set [`$debugging`](../programmers/api-variables/variable-debugging.md) to TRUE in Smarty, and if needed
set [`$debug_tpl`](../programmers/api-variables/variable-debug-template.md) to the template resource
path to `debug.tpl` (this is in [`SMARTY_DIR`](../programmers/smarty-constants.md) by
default). When you load the page, a Javascript console window will pop
up and give you the names of all the included templates and assigned
variables for the current page.
To see the available variables for a particular template, see the
[`{debug}`](./language-builtin-functions/language-function-debug.md) template function. To disable the
debugging console, set [`$debugging`](../programmers/api-variables/variable-debugging.md) to FALSE. You
can also temporarily turn on the debugging console by putting
`SMARTY_DEBUG` in the URL if you enable this option with
[`$debugging_ctrl`](../programmers/api-variables/variable-debugging-ctrl.md).
> **Note**
>
> The debugging console does not work when you use the
> [`fetch()`](../programmers/api-functions/api-fetch.md) API, only when using
> [`display()`](../programmers/api-functions/api-display.md). It is a set of javascript statements
> added to the very bottom of the generated template. If you do not like
> javascript, you can edit the `debug.tpl` template to format the output
> however you like. Debug data is not cached and `debug.tpl` info is not
> included in the output of the debug console.
> **Note**
>
> The load times of each template and config file are in seconds, or
> fractions thereof.
See also [troubleshooting](../appendixes/troubleshooting.md).

View File

@@ -1,77 +0,0 @@
Config Files {#config.files}
============
Config files are handy for designers to manage global template variables
from one file. One example is template colors. Normally if you wanted to
change the color scheme of an application, you would have to go through
each and every template file and change the colors. With a config file,
the colors can be kept in one place, and only one file needs to be
updated.
# global variables
pageTitle = "Main Menu"
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
[Customer]
pageTitle = "Customer Info"
[Login]
pageTitle = "Login"
focus = "username"
Intro = """This is a value that spans more
than one line. you must enclose
it in triple quotes."""
# hidden section
[.Database]
host=my.example.com
db=ADDRESSBOOK
user=php-user
pass=foobar
Values of [config file variables](./language-variables/language-config-variables.md) can be in
quotes, but not necessary. You can use either single or double quotes.
If you have a value that spans more than one line, enclose the entire
value with triple quotes (\"\"\"). You can put comments into config
files by any syntax that is not a valid config file syntax. We recommend
using a `
#` (hash) at the beginning of the line.
The example config file above has two sections. Section names are
enclosed in \[brackets\]. Section names can be arbitrary strings not
containing `[` or `]` symbols. The four variables at the top are global
variables, or variables not within a section. These variables are always
loaded from the config file. If a particular section is loaded, then the
global variables and the variables from that section are also loaded. If
a variable exists both as a global and in a section, the section
variable is used. If you name two variables the same within a section,
the last one will be used unless
[`$config_overwrite`](../programmers/api-variables/variable-config-overwrite.md) is disabled.
Config files are loaded into templates with the built-in template
function [`
{config_load}`](./language-builtin-functions/language-function-config-load.md) or the API
[`configLoad()`](../programmers/api-functions/api-config-load.md) function.
You can hide variables or entire sections by prepending the variable
name or section name with a period(.) eg `[.hidden]`. This is useful if
your application reads the config files and gets sensitive data from
them that the template engine does not need. If you have third parties
doing template editing, you can be certain that they cannot read
sensitive data from the config file by loading it into the template.
Config files (or resources) are loaded by the same resource facilities
as templates. That means that a config file can also be loaded from a db
`$smarty->configLoad("db:my.conf")`.
See also [`{config_load}`](./language-builtin-functions/language-function-config-load.md),
[`$config_overwrite`](../programmers/api-variables/variable-config-overwrite.md),
[`$default_config_handler_func`](../programmers/api-variables/variable-default-config-handler-func.md),
[`getConfigVars()`](../programmers/api-functions/api-get-config-vars.md),
[`clearConfig()`](../programmers/api-functions/api-clear-config.md) and
[`configLoad()`](../programmers/api-functions/api-config-load.md)

View File

@@ -1,33 +0,0 @@
Basic Syntax
============
A simple Smarty template could look like this:
```html
<h1>{$title|escape}</h1>
<ul>
{foreach $cities as $city}
<li>{$city.name|escape} ({$city.population})</li>
{foreachelse}
<li>no cities found</li>
{/foreach}
</ul>
```
All Smarty template tags are enclosed within delimiters. By default
these are `{` and `}`, but they can be
[changed](../programmers/api-variables/variable-left-delimiter.md).
For the examples in this manual, we will assume that you are using the
default delimiters. In Smarty, all content outside of delimiters is
displayed as static content, or unchanged. When Smarty encounters
template tags, it attempts to interpret them, and displays the
appropriate output in their place.
The basis components of the Smarty syntax are:
- [Comments](./language-basic-syntax/language-syntax-comments.md)
- [Variables](./language-basic-syntax/language-syntax-variables.md)
- [Functions](./language-basic-syntax/language-syntax-functions.md)
- [Attributes](./language-basic-syntax/language-syntax-attributes.md)
- [Quotes](./language-basic-syntax/language-syntax-quotes.md)
- [Math](./language-basic-syntax/language-math.md)
- [Escaping](./language-basic-syntax/language-escaping.md)

View File

@@ -1,84 +0,0 @@
Escaping Smarty Parsing {#language.escaping}
=======================
It is sometimes desirable or even necessary to have Smarty ignore
sections it would otherwise parse. A classic example is embedding
Javascript or CSS code in a template. The problem arises as those
languages use the { and } characters which are also the default
[delimiters](#language.function.ldelim) for Smarty.
> **Note**
>
> A good practice for avoiding escapement altogether is by separating
> your Javascript/CSS into their own files and use standard HTML methods
> to access them. This will also take advantage of browser script
> caching. When you need to embed Smarty variables/functions into your
> Javascript/CSS, then the following applies.
In Smarty templates, the { and } braces will be ignored so long as they
are surrounded by white space. This behavior can be disabled by setting
the Smarty class variable [`$auto_literal`](#variable.auto.literal) to
false.
<script>
// the following braces are ignored by Smarty
// since they are surrounded by whitespace
function foobar {
alert('foobar!');
}
// this one will need literal escapement
{literal}
function bazzy {alert('foobar!');}
{/literal}
</script>
[`{literal}..{/literal}`](#language.function.literal) blocks are used
for escaping blocks of template logic. You can also escape the braces
individually with
[`{ldelim}`](#language.function.ldelim),[`{rdelim}`](#language.function.ldelim)
tags or
[`{$smarty.ldelim}`,`{$smarty.rdelim}`](#language.variables.smarty.ldelim)
variables.
Smarty\'s default delimiters { and } cleanly represent presentational
content. However if another set of delimiters suit your needs better,
you can change them with Smarty\'s
[`$left_delimiter`](#variable.left.delimiter) and
[`$right_delimiter`](#variable.right.delimiter) values.
> **Note**
>
> Changing delimiters affects ALL template syntax and escapement. Be
> sure to clear out cache and compiled files if you decide to change
> them.
<?php
$smarty->left_delimiter = '<!--{';
$smarty->right_delimiter = '}-->';
$smarty->assign('foo', 'bar');
$smarty->assign('name', 'Albert');
$smarty->display('example.tpl');
?>
Where the template is:
Welcome <!--{$name}--> to Smarty
<script language="javascript">
var foo = <!--{$foo}-->;
function dosomething() {
alert("foo is " + foo);
}
dosomething();
</script>

View File

@@ -1,29 +0,0 @@
Math {#language.math}
====
Math can be applied directly to variable values.
{$foo+1}
{$foo*$bar}
{* some more complicated examples *}
{$foo->bar-$bar[1]*$baz->foo->bar()-3*7}
{if ($foo+$bar.test%$baz*134232+10+$b+10)}
{$foo|truncate:"`$fooTruncCount/$barTruncFactor-1`"}
{assign var="foo" value="`$foo+$bar`"}
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.

View File

@@ -1,50 +0,0 @@
Attributes {#language.syntax.attributes}
==========
Most of the [functions](#language.syntax.functions) take attributes that
specify or modify their behavior. Attributes to Smarty functions are
much like HTML attributes. Static values don\'t have to be enclosed in
quotes, but it is required for literal strings. Variables with or
without modifiers may also be used, and should not be in quotes. You can
even use PHP function results, plugin results and complex expressions.
Some attributes require boolean values (TRUE or FALSE). These can be
specified as `true` and `false`. If an attribute has no value assigned
it gets the default boolean value of true.
{include file="header.tpl"}
{include file="header.tpl" nocache} // is equivalent to nocache=true
{include file="header.tpl" attrib_name="attrib value"}
{include file=$includeFile}
{include file=#includeFile# title="My Title"}
{assign var=foo value={counter}} // plugin result
{assign var=foo value=substr($bar,2,5)} // PHP function result
{assign var=foo value=$bar|strlen} // using modifier
{assign var=foo value=$buh+$bar|strlen} // more complex expression
{html_select_date display_days=true}
{mailto address="smarty@example.com"}
<select name="company_id">
{html_options options=$companies selected=$company_id}
</select>
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.

View File

@@ -1,71 +0,0 @@
Comments {#language.syntax.comments}
========
Template comments are surrounded by asterisks, and that is surrounded by
the [delimiter](#variable.left.delimiter) tags like so:
::: {.informalexample}
{* this is a comment *}
:::
Smarty comments are NOT displayed in the final output of the template,
unlike `<!-- HTML comments -->`. These are useful for making internal
notes in the templates which no one will see ;-)
{* I am a Smarty comment, I don't exist in the compiled output *}
<html>
<head>
<title>{$title}</title>
</head>
<body>
{* another single line smarty comment *}
<!-- HTML comment that is sent to the browser -->
{* this multiline smarty
comment is
not sent to browser
*}
{*********************************************************
Multi line comment block with credits block
@ author: bg@example.com
@ maintainer: support@example.com
@ para: var that sets block style
@ css: the style output
**********************************************************}
{* The header file with the main logo and stuff *}
{include file='header.tpl'}
{* Dev note: the $includeFile var is assigned in foo.php script *}
<!-- Displays main content block -->
{include file=$includeFile}
{* this <select> block is redundant *}
{*
<select name="company">
{html_options options=$vals selected=$selected_id}
</select>
*}
<!-- Show header from affiliate is disabled -->
{* $affiliate|upper *}
{* you cannot nest comments *}
{*
<select name="company">
{* <option value="0">-- none -- </option> *}
{html_options options=$vals selected=$selected_id}
</select>
*}
</body>
</html>

View File

@@ -1,40 +0,0 @@
Functions {#language.syntax.functions}
=========
Every Smarty tag either prints a [variable](#language.variables) or
invokes some sort of function. These are processed and displayed by
enclosing the function and its [attributes](#language.syntax.attributes)
within delimiters like so: `{funcname attr1="val1" attr2="val2"}`.
{config_load file="colors.conf"}
{include file="header.tpl"}
{insert file="banner_ads.tpl" title="My Site"}
{if $logged_in}
Welcome, <span style="color:{#fontColor#}">{$name}!</span>
{else}
hi, {$name}
{/if}
{include file="footer.tpl"}
- Both [built-in functions](#language.builtin.functions) and [custom
functions](#language.custom.functions) have the same syntax within
templates.
- Built-in functions are the **inner** workings of Smarty, such as
[`{if}`](#language.function.if),
[`{section}`](#language.function.section) and
[`{strip}`](#language.function.strip). There should be no need to
change or modify them.
- Custom functions are **additional** functions implemented via
[plugins](#plugins). They can be modified to your liking, or you can
create new ones. [`{html_options}`](#language.function.html.options)
is an example of a custom function.
See also [`registerPlugin()`](#api.register.plugin)

View File

@@ -1,61 +0,0 @@
Embedding Vars in Double Quotes {#language.syntax.quotes}
===============================
- Smarty will recognize [assigned](#api.assign)
[variables](#language.syntax.variables) embedded in \"double
quotes\" so long as the variable name contains only numbers, letters
and under\_scores. See [naming](&url.php-manual;language.variables)
for more detail.
- With any other characters, for example a period(.) or
`$object->reference`, then the variable must be surrounded by
`` `backticks` ``.
- In addition Smarty3 does allow embedded Smarty tags in double quoted
strings. This is useful if you want to include variables with
modifiers, plugin or PHP function results.
<!-- -->
{func var="test $foo test"} // sees $foo
{func var="test $foo_bar test"} // sees $foo_bar
{func var="test `$foo[0]` test"} // sees $foo[0]
{func var="test `$foo[bar]` test"} // sees $foo[bar]
{func var="test $foo.bar test"} // sees $foo (not $foo.bar)
{func var="test `$foo.bar` test"} // sees $foo.bar
{func var="test `$foo.bar` test"|escape} // modifiers outside quotes!
{func var="test {$foo|escape} test"} // modifiers inside quotes!
{func var="test {time()} test"} // PHP function result
{func var="test {counter} test"} // plugin result
{func var="variable foo is {if !$foo}not {/if} defined"} // Smarty block function
{* will replace $tpl_name with value *}
{include file="subdir/$tpl_name.tpl"}
{* does NOT replace $tpl_name *}
{include file='subdir/$tpl_name.tpl'} // vars require double quotes!
{* must have backticks as it contains a dot "." *}
{cycle values="one,two,`$smarty.config.myval`"}
{* must have backticks as it contains a dot "." *}
{include file="`$module.contact`.tpl"}
{* can use variable with dot syntax *}
{include file="`$module.$view`.tpl"}
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
See also [`escape`](#language.modifier.escape).

View File

@@ -1,111 +0,0 @@
Variables {#language.syntax.variables}
=========
Template variables start with the \$dollar sign. They can contain
numbers, letters and underscores, much like a [PHP
variable](&url.php-manual;language.variables). You can reference arrays
by index numerically or non-numerically. Also reference object
properties and methods.
[Config file variables](#language.config.variables) are an exception to
the \$dollar syntax and are instead referenced with surrounding
\#hashmarks\#, or via the
[`$smarty.config`](#language.variables.smarty.config) variable.
{$foo} <-- displaying a simple variable (non array/object)
{$foo[4]} <-- display the 5th element of a zero-indexed array
{$foo.bar} <-- display the "bar" key value of an array, similar to PHP $foo['bar']
{$foo.$bar} <-- display variable key value of an array, similar to PHP $foo[$bar]
{$foo->bar} <-- display the object property "bar"
{$foo->bar()} <-- display the return value of object method "bar"
{#foo#} <-- display the config file variable "foo"
{$smarty.config.foo} <-- synonym for {#foo#}
{$foo[bar]} <-- syntax only valid in a section loop, see {section}
{assign var=foo value='baa'}{$foo} <-- displays "baa", see {assign}
Many other combinations are allowed
{$foo.bar.baz}
{$foo.$bar.$baz}
{$foo[4].baz}
{$foo[4].$baz}
{$foo.bar.baz[4]}
{$foo->bar($baz,2,$bar)} <-- passing parameters
{"foo"} <-- static values are allowed
{* display the server variable "SERVER_NAME" ($_SERVER['SERVER_NAME'])*}
{$smarty.server.SERVER_NAME}
Math and embedding tags:
{$x+$y} // will output the sum of x and y.
{assign var=foo value=$x+$y} // in attributes
{$foo[$x+3]} // as array index
{$foo={counter}+3} // tags within tags
{$foo="this is message {counter}"} // tags within double quoted strings
Defining Arrays:
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
{assign var=foo value=[1,[9,8],3]} // can be nested
Short variable assignment:
{$foo=$bar+2}
{$foo = strlen($bar)} // function in assignment
{$foo = myfunct( ($x+$y)*3 )} // as function parameter
{$foo.bar=1} // assign to specific array element
{$foo.bar.baz=1}
{$foo[]=1} // appending to an array
Smarty "dot" syntax (note: embedded {} are used to address ambiguities):
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c'] // with variable index
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c'] // with expression as index
{$foo.a.{$b.c}} => $foo['a'][$b['c']] // with nested index
PHP-like syntax, alternative to "dot" syntax:
{$foo[1]} // normal access
{$foo['bar']}
{$foo['bar'][1]}
{$foo[$x+$x]} // index may contain any expression
{$foo[$bar[1]]} // nested index
{$foo[section_name]} // smarty {section} access, not array access!
Variable variables:
$foo // normal variable
$foo_{$bar} // variable name containing other variable
$foo_{$x+$y} // variable name containing expressions
$foo_{$bar}_buh_{$blar} // variable name with multiple segments
{$foo_{$x}} // will output the variable $foo_1 if $x has a value of 1.
Object chaining:
{$object->method1($x)->method2($y)}
Direct PHP function access:
{time()}
> **Note**
>
> Although Smarty can handle some very complex expressions and syntax,
> it is a good rule of thumb to keep the template syntax minimal and
> focused on presentation. If you find your template syntax getting too
> complex, it may be a good idea to move the bits that do not deal
> explicitly with presentation to PHP by way of plugins or modifiers.
Request variables such as `$_GET`, `$_SESSION`, etc are available via
the reserved [`$smarty`](#language.variables.smarty) variable.
See also [`$smarty`](#language.variables.smarty), [config
variables](#language.config.variables)
[`{assign}`](#language.function.assign) and [`assign()`](#api.assign).

View File

@@ -1,39 +0,0 @@
Built-in Functions {#language.builtin.functions}
==================
## Table of contents
- [{$var=...}](./language-builtin-functions/language-function-shortform-assign.md)
- [{append}](./language-builtin-functions/language-function-append.md)
- [{assign}](./language-builtin-functions/language-function-assign.md)
- [{block}](./language-builtin-functions/language-function-block.md)
- [{call}](./language-builtin-functions/language-function-call.md)
- [{capture}](./language-builtin-functions/language-function-capture.md)
- [{config_load}](./language-builtin-functions/language-function-config.load)
- [{debug}](./language-builtin-functions/language-function-debug.md)
- [{extends}](./language-builtin-functions/language-function-extends.md)
- [{for}](./language-builtin-functions/language-function-for.md)
- [{foreach},{foreachelse}](./language-builtin-functions/language-function-foreach.md)
- [{function}](./language-builtin-functions/language-function-function.md)
- [{if},{elseif},{else}](./language-builtin-functions/language-function-if.md)
- [{include}](./language-builtin-functions/language-function-include.md)
- [{include_php}](./language-builtin-functions/language-function-include.php)
- [{insert}](./language-builtin-functions/language-function-insert.md)
- [{ldelim},{rdelim}](./language-builtin-functions/language-function-ldelim.md)
- [{literal}](./language-builtin-functions/language-function-literal.md)
- [{nocache}](./language-builtin-functions/language-function-nocache.md)
- [{section},{sectionelse}](./language-builtin-functions/language-function-section.md)
- [{setfilter}](./language-builtin-functions/language-function-setfilter.md)
- [{strip}](./language-builtin-functions/language-function-strip.md)
- [{while}](./language-builtin-functions/language-function-while.md)
Smarty comes with several built-in functions. These built-in functions
are the integral part of the smarty template engine. They are compiled
into corresponding inline PHP code for maximum performance.
You cannot create your own [custom
functions](./language-custom-functions.md) with the same name; and you
should not need to modify the built-in functions.
A few of these functions have an `assign` attribute which collects the
result the function to a named template variable instead of being
output; much like the [`{assign}`](./language-builtin-functions/language-function-assign.md) function.

View File

@@ -1,49 +0,0 @@
{append} {#language.function.append}
========
`{append}` is used for creating or appending template variable arrays
**during the execution of a template**.
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ----------------------------------------------------------------------------------------------------
var string Yes *n/a* The name of the variable being assigned
value string Yes *n/a* The value being assigned
index string No *n/a* The index for the new array element. If not specified the value is append to the end of the array.
scope string No *n/a* The scope of the assigned variable: \'parent\',\'root\' or \'global\'
**Option Flags:**
Name Description
--------- -----------------------------------------------------
nocache Assigns the variable with the \'nocache\' attribute
{append var='name' value='Bob' index='first'}
{append var='name' value='Meyer' index='last'}
// or
{append 'name' 'Bob' index='first'} {* short-hand *}
{append 'name' 'Meyer' index='last'} {* short-hand *}
The first name is {$name.first}.<br>
The last name is {$name.last}.
The above example will output:
The first name is Bob.
The last name is Meyer.
See also [`append()`](#api.append) and
[`getTemplateVars()`](#api.get.template.vars).

View File

@@ -1,149 +0,0 @@
{assign} {#language.function.assign}
========
`{assign}` is used for assigning template variables **during the
execution of a template**.
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
> **Note**
>
> See also the [`short-form`](#language.function.shortform.assign)
> method of assigning template vars.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- -----------------------------------------------------------------------
var string Yes *n/a* The name of the variable being assigned
value string Yes *n/a* The value being assigned
scope string No *n/a* The scope of the assigned variable: \'parent\',\'root\' or \'global\'
**Option Flags:**
Name Description
--------- -----------------------------------------------------
nocache Assigns the variable with the \'nocache\' attribute
{assign var="name" value="Bob"}
{assign "name" "Bob"} {* short-hand *}
The value of $name is {$name}.
The above example will output:
The value of $name is Bob.
{assign var="name" value="Bob" nocache}
{assign "name" "Bob" nocache} {* short-hand *}
The value of $name is {$name}.
The above example will output:
The value of $name is Bob.
{assign var=running_total value=$running_total+$some_array[$row].some_value}
Variables assigned in the included template will be seen in the
including template.
{include file="sub_template.tpl"}
...
{* display variable assigned in sub_template *}
{$foo}<br>
...
The template above includes the example `sub_template.tpl` below
...
{* foo will be known also in the including template *}
{assign var="foo" value="something" scope=parent}
{* bar is assigned only local in the including template *}
{assign var="bar" value="value"}
...
You can assign a variable to root of the current root tree. The variable
is seen by all templates using the same root tree.
{assign var=foo value="bar" scope="root"}
A global variable is seen by all templates.
{assign var=foo value="bar" scope="global"}
{assign "foo" "bar" scope="global"} {* short-hand *}
To access `{assign}` variables from a php script use
[`getTemplateVars()`](#api.get.template.vars). Here\'s the template that
creates the variable `$foo`.
{assign var="foo" value="Smarty"}
The template variables are only available after/during template
execution as in the following script.
<?php
// this will output nothing as the template has not been executed
echo $smarty->getTemplateVars('foo');
// fetch the template to a variable
$whole_page = $smarty->fetch('index.tpl');
// this will output 'smarty' as the template has been executed
echo $smarty->getTemplateVars('foo');
$smarty->assign('foo','Even smarter');
// this will output 'Even smarter'
echo $smarty->getTemplateVars('foo');
?>
The following functions can also *optionally* assign template variables.
[`{capture}`](#language.function.capture),
[`{include}`](#language.function.include),
[`{include_php}`](#language.function.include.php),
[`{insert}`](#language.function.insert),
[`{counter}`](#language.function.counter),
[`{cycle}`](#language.function.cycle),
[`{eval}`](#language.function.eval),
[`{fetch}`](#language.function.fetch),
[`{math}`](#language.function.math),
[`{textformat}`](#language.function.textformat)
See also [`{$var=...}`](#language.function.shortform.assign),
[`assign()`](#api.assign) and
[`getTemplateVars()`](#api.get.template.vars).

View File

@@ -1,191 +0,0 @@
{block} {#language.function.block}
=======
`{block}` is used to define a named area of template source for template
inheritance. For details see section of [Template
Interitance](#advanced.features.template.inheritance).
The `{block}` template source area of a child template will replace the
correponding areas in the parent template(s).
Optionally `{block}` areas of child and parent templates can be merged
into each other. You can append or prepend the parent `{block}` content
by using the `append` or `prepend` option flag with the childs `{block}`
definition. With the {\$smarty.block.parent} the `{block}` content of
the parent template can be inserted at any location of the child
`{block}` content. {\$smarty.block.child} inserts the `{block}` content
of the child template at any location of the parent `{block}`.
`{blocks}'s` can be nested.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ---------------------------------------
name string Yes *n/a* The name of the template source block
**Option Flags (in child templates only):**
Name Description
--------- -------------------------------------------------------------------------------------------
append The `{block}` content will be be appended to the content of the parent template `{block}`
prepend The `{block}` content will be prepended to the content of the parent template `{block}`
hide Ignore the block content if no child block of same name is existing.
nocache Disables caching of the `{block}` content
parent.tpl
<html>
<head>
<title>{block name="title"}Default Title{/block}</title>
<title>{block "title"}Default Title{/block}</title> {* short-hand *}
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Page Title</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}Title - {/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title" prepend}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Title - Page Title</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"} is my title{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title" append}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Page title is my titel</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}The {$smarty.block.child} was inserted here{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
Child Title
{/block}
The result would look like
<html>
<head>
<title>The Child Title was inserted here</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}Parent Title{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
You will see now - {$smarty.block.parent} - here
{/block}
The result would look like
<html>
<head>
<title>You will see now - Parent Title - here</title>
</head>
</html>
See also [Template
Inheritance](#advanced.features.template.inheritance),
[`$smarty.block.parent`](#language.variables.smarty.block.parent),
[`$smarty.block.child`](#language.variables.smarty.block.child), and
[`{extends}`](#language.function.extends)

View File

@@ -1,76 +0,0 @@
{call} {#language.function.call}
======
`{call}` is used to call a template function defined by the
[`{function}`](#language.function.function) tag just like a plugin
function.
> **Note**
>
> Template functions are defined global. Since the Smarty compiler is a
> single-pass compiler, The [`{call}`](#language.function.call) tag must
> be used to call a template function defined externally from the given
> template. Otherwise you can directly use the function as
> `{funcname ...}` in the template.
- The `{call}` tag must have the `name` attribute which contains the
the name of the template function.
- Values for variables can be passed to the template function as
[attributes](#language.syntax.attributes).
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------------- ---------- --------- ------------------------------------------------------------------------------------------
name string Yes *n/a* The name of the template function
assign string No *n/a* The name of the variable that the output of called template function will be assigned to
\[var \...\] \[var type\] No *n/a* variable to pass local to template function
**Option Flags:**
Name Description
--------- --------------------------------------------
nocache Call the template function in nocache mode
{* define the function *}
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{* create an array to demonstrate *}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{* run the array through the function *}
{call name=menu data=$menu}
{call menu data=$menu} {* short-hand *}
Will generate the following output
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
See also [`{function}`](#language.function.function)

View File

@@ -1,82 +0,0 @@
{capture} {#language.function.capture}
=========
`{capture}` is used to collect the output of the template between the
tags into a variable instead of displaying it. Any content between
`{capture name='foo'}` and `{/capture}` is collected into the variable
specified in the `name` attribute.
The captured content can be used in the template from the variable
[`$smarty.capture.foo`](#language.variables.smarty.capture) where "foo"
is the value passed in the `name` attribute. If you do not supply the
`name` attribute, then "default" will be used as the name ie
`$smarty.capture.default`.
`{capture}'s` can be nested.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ----------------------------------------------------------------------
name string Yes *n/a* The name of the captured block
assign string No *n/a* The variable name where to assign the captured output to
append string No *n/a* The name of an array variable where to append the captured output to
**Option Flags:**
Name Description
--------- -----------------------------------------
nocache Disables caching of this captured block
> **Note**
>
> Be careful when capturing [`{insert}`](#language.function.insert)
> output. If you have [`$caching`](#caching) enabled and you have
> [`{insert}`](#language.function.insert) commands that you expect to
> run within cached content, do not capture this content.
{* we don't want to print a div tag unless content is displayed *}
{capture name="banner"}
{capture "banner"} {* short-hand *}
{include file="get_banner.tpl"}
{/capture}
{if $smarty.capture.banner ne ""}
<div id="banner">{$smarty.capture.banner}</div>
{/if}
This example demonstrates the capture function.
{capture name=some_content assign=popText}
{capture some_content assign=popText} {* short-hand *}
The server is {$my_server_name|upper} at {$my_server_addr}<br>
Your ip is {$my_ip}.
{/capture}
<a href="#">{$popText}</a>
This example also demonstrates how multiple calls of capture can be used
to create an array with captured content.
{capture append="foo"}hello{/capture}I say just {capture append="foo"}world{/capture}
{foreach $foo as $text}{$text} {/foreach}
The above example will output:
I say just hello world
See also [`$smarty.capture`](#language.variables.smarty.capture),
[`{eval}`](#language.function.eval),
[`{fetch}`](#language.function.fetch), [`fetch()`](#api.fetch) and
[`{assign}`](#language.function.assign).

View File

@@ -1,91 +0,0 @@
{config\_load} {#language.function.config.load}
==============
`{config_load}` is used for loading config
[`#variables#`](#language.config.variables) from a [configuration
file](#config.files) into the template.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
file string Yes *n/a* The name of the config file to include
section string No *n/a* The name of the section to load
scope string no *local* How the scope of the loaded variables are treated, which must be one of local, parent or global. local means variables are loaded into the local template context. parent means variables are loaded into both the local context and the parent template that called it. global means variables are available to all templates.
The `example.conf` file.
#this is config file comment
# global variables
pageTitle = "Main Menu"
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
#customer variables section
[Customer]
pageTitle = "Customer Info"
and the template
{config_load file="example.conf"}
{config_load "example.conf"} {* short-hand *}
<html>
<title>{#pageTitle#|default:"No title"}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
[Config Files](#config.files) may also contain sections. You can load
variables from within a section with the added attribute `section`. Note
that global config variables are always loaded along with section
variables, and same-named section variables overwrite the globals.
> **Note**
>
> Config file *sections* and the built-in template function called
> [`{section}`](#language.function.section) have nothing to do with each
> other, they just happen to share a common naming convention.
{config_load file='example.conf' section='Customer'}
{config_load 'example.conf' 'Customer'} {* short-hand *}
<html>
<title>{#pageTitle#}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
See [`$config_overwrite`](#variable.config.overwrite) to create arrays
of config file variables.
See also the [config files](#config.files) page, [config
variables](#language.config.variables) page,
[`$config_dir`](#variable.config.dir),
[`getConfigVars()`](#api.get.config.vars) and
[`configLoad()`](#api.config.load).

View File

@@ -1,18 +0,0 @@
{debug} {#language.function.debug}
=======
`{debug}` dumps the debug console to the page. This works regardless of
the [debug](#chapter.debugging.console) settings in the php script.
Since this gets executed at runtime, this is only able to show the
[assigned](#api.assign) variables; not the templates that are in use.
However, you can see all the currently available variables within the
scope of a template.
If caching is enabled and a page is loaded from cache `{debug}` does
show only the variables which assigned for the cached page.
In order to see also the variables which have been locally assigned
within the template it does make sense to place the `{debug}` tag at the
end of the template.
See also the [debugging console page](#chapter.debugging.console).

Some files were not shown because too many files have changed in this diff Show More