Commit d28b523a authored by Carsten  Rose's avatar Carsten Rose
Browse files

Input Field date / datetime / time implemented.

AdministratorManual/index.rst, UsersManual/index.rst: Configuration & Documentation.
Sanitize.php: code rewrote to use Support::dateTime2mysql().
Support.php: add dateTimeTegexp()
FillStoreForm.php: use of Support::setFeDefaults($formElement). Format date/datetime/time values
Store.php: redefined various functions to be 'static'
AbstractBuildForm.php, Constants.php: added date/datetime/time to tables. Various new functions.
Save.php: FE die nicht uebertragen wurden (typsicherweise weil leer) werden neu mit eimem leer String gesschrieben - sonst ist es nicht moeglich  Eingaben wieder zu loeschen.
formEditor.sql: Felder date/datetime/time neun implementiert.
parent 810b81b6
...@@ -101,6 +101,8 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content ...@@ -101,6 +101,8 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content
+------------------------+----------------------------------+----------------------------------------------------------------------------+ +------------------------+----------------------------------+----------------------------------------------------------------------------+
| CSS_LINK_CLASS_EXTERNAL| CSS_LINK_CLASS_EXTERNAL=external | CSS class name of links which points to internal tagets | | CSS_LINK_CLASS_EXTERNAL| CSS_LINK_CLASS_EXTERNAL=external | CSS class name of links which points to internal tagets |
+------------------------+----------------------------------+----------------------------------------------------------------------------+ +------------------------+----------------------------------+----------------------------------------------------------------------------+
| DATE_FORMAT | DATE_FORMAT= yyyy-mm-dd | Possible options: yyyy-mm-dd, dd.mm.yyyy |
+------------------------+----------------------------------+----------------------------------------------------------------------------+
Example: *<ext_dir>/config.ini* Example: *<ext_dir>/config.ini*
......
...@@ -507,9 +507,10 @@ Class: Native ...@@ -507,9 +507,10 @@ Class: Native
|class | enum('native', 'action', | Details below. | |class | enum('native', 'action', | Details below. |
| | 'container') | | | | 'container') | |
+--------------+-----------------------------+---------------------------------------------------------------------------------------------------+ +--------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|type | enum('checkbox', 'dateJQW', 'datetimeJQW', 'gridJQW', 'hidden', 'text', 'note', 'password', 'radio', 'select', 'subrecord', | |type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'gridJQW', 'hidden', 'text', 'note', 'password', |
| | 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'before_load', 'before_save', 'before_insert', 'before_update', | | | 'radio', 'select', 'subrecord', 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'before_load', 'before_save', |
| | 'before_delete', 'after_load', 'after_save', 'after_insert', 'after_update', 'after_delete', 'feGroup', 'sendmail') | | | 'before_insert', 'before_update', 'before_delete', 'after_load', 'after_save', 'after_insert', 'after_update', 'after_delete', |
| | 'feGroup', 'sendmail') |
+--------------+-----------------------------+---------------------------------------------------------------------------------------------------+ +--------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|checkType | enum('min|max', 'pattern', | | |checkType | enum('min|max', 'pattern', | |
| | 'number', 'email') | | | | 'number', 'email') | |
...@@ -685,9 +686,19 @@ Checkboxes can be rendered in mode: ...@@ -685,9 +686,19 @@ Checkboxes can be rendered in mode:
Type: date Type: date
^^^^^^^^^^ ^^^^^^^^^^
* Range datetime: '1000-01-01' to '9999-12-31' or '0000-00-00'. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
* Optional:
* *dateFormat*: ; yyyy-mm-dd | dd.mm.yyyy
Type: datetime Type: datetime
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
* Range datetime: '1000-01-01 00:00:00' to '9999-12-31 23:59:59' or '0000-00-00 00:00:00'. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
* Optional:
* *dateFormat*: ; yyyy-mm-dd | dd.mm.yyyy
* *showSeconds*: 0|1 - shows the seconds. Independent if the user specifies seconds, they are displayed '1' or not '0'.
* *showZero*: 0|1 - For an empty timestamp, With '0' nothing is displayed. With '1' the string '0000-00-00 00:00:00' is displayed.
Type: hidden Type: hidden
^^^^^^^^^^^^ ^^^^^^^^^^^^
...@@ -807,6 +818,11 @@ Typically not used. Useful if user wishes an explicit 'Submit' Button. ...@@ -807,6 +818,11 @@ Typically not used. Useful if user wishes an explicit 'Submit' Button.
Type: time Type: time
^^^^^^^^^^ ^^^^^^^^^^
* Range time: '00:00:00' to '23:59:59' or '00:00:00'. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
* Optional:
* *showSeconds*: 0|1 - shows the seconds. Independent if the user specifies seconds, they are displayed '1' or not '0'.
* *showZero*: 0|1 - For an empty timestamp, With '0' nothing is displayed. With '1' the string '00:00[:00]' is displayed.
Type: upload Type: upload
^^^^^^^^^^^^ ^^^^^^^^^^^^
......
...@@ -20,3 +20,6 @@ CSS_LINK_CLASS_EXTERNAL = external ...@@ -20,3 +20,6 @@ CSS_LINK_CLASS_EXTERNAL = external
; QFQ with own Bootstrap: 'container'. QFQ already nested in Bootstrap of mainpage: <empty> ; QFQ with own Bootstrap: 'container'. QFQ already nested in Bootstrap of mainpage: <empty>
CSS_CLASS_QFQ_CONTAINER = CSS_CLASS_QFQ_CONTAINER =
; yyyy-mm-dd, dd.mm.yyyy
DATE_FORMAT = yyyy-mm-dd
...@@ -9,8 +9,8 @@ namespace qfq; ...@@ -9,8 +9,8 @@ namespace qfq;
use qfq; use qfq;
use qfq\Store; use qfq\Store;
use qfq\UserFormException;
use qfq\OnArray; use qfq\OnArray;
use qfq\UserFormException;
require_once(__DIR__ . '/../qfq/store/Store.php'); require_once(__DIR__ . '/../qfq/store/Store.php');
require_once(__DIR__ . '/../qfq/Constants.php'); require_once(__DIR__ . '/../qfq/Constants.php');
...@@ -66,12 +66,15 @@ abstract class AbstractBuildForm { ...@@ -66,12 +66,15 @@ abstract class AbstractBuildForm {
$this->buildElementFunctionName = [ $this->buildElementFunctionName = [
'checkbox' => 'Checkbox', 'checkbox' => 'Checkbox',
'date' => 'DateTime',
'datetime' => 'DateTime',
'dateJQW' => 'DateJQW', 'dateJQW' => 'DateJQW',
'datetimeJQW' => 'DateJQW', 'datetimeJQW' => 'DateJQW',
'email' => 'Input', 'email' => 'Input',
'gridJQW' => 'GridJQW', 'gridJQW' => 'GridJQW',
'hidden' => 'Hidden', 'hidden' => 'Hidden',
'text' => 'Input', 'text' => 'Input',
'time' => 'DateTime',
'note' => 'Note', 'note' => 'Note',
'password' => 'Input', 'password' => 'Input',
'radio' => 'Radio', 'radio' => 'Radio',
...@@ -84,12 +87,15 @@ abstract class AbstractBuildForm { ...@@ -84,12 +87,15 @@ abstract class AbstractBuildForm {
$this->buildRowName = [ $this->buildRowName = [
'checkbox' => 'Native', 'checkbox' => 'Native',
'date' => 'Native',
'datetime' => 'Native',
'dateJQW' => 'Native', 'dateJQW' => 'Native',
'datetimeJQW' => 'Native', 'datetimeJQW' => 'Native',
'email' => 'Native', 'email' => 'Native',
'gridJQW' => 'Native', 'gridJQW' => 'Native',
'hidden' => 'Native', 'hidden' => 'Native',
'text' => 'Native', 'text' => 'Native',
'time' => 'Native',
'note' => 'Native', 'note' => 'Native',
'password' => 'Native', 'password' => 'Native',
'radio' => 'Native', 'radio' => 'Native',
...@@ -124,7 +130,14 @@ abstract class AbstractBuildForm { ...@@ -124,7 +130,14 @@ abstract class AbstractBuildForm {
$htmlSubrecords = ''; $htmlSubrecords = '';
$htmlElements = ''; $htmlElements = '';
$json = array(); $json = array();
$modeCollectFe = ($mode === FORM_SAVE) ? FLAG_ALL : FLAG_DYNAMIC_UPDATE;
$modeCollectFe = FLAG_DYNAMIC_UPDATE;
$storeUse = STORE_USE_DEFAULT;
if ($mode === FORM_SAVE) {
$modeCollectFe = FLAG_ALL;
$storeUse = STORE_RECORD . STORE_TABLE_DEFAULT;
}
// <form> // <form>
if ($mode === FORM_LOAD) { if ($mode === FORM_LOAD) {
...@@ -145,7 +158,7 @@ abstract class AbstractBuildForm { ...@@ -145,7 +158,7 @@ abstract class AbstractBuildForm {
$json[] = $jsonTmp; $json[] = $jsonTmp;
} }
} else { } else {
$htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json, $modeCollectFe, $htmlElementNameIdZero); $htmlElements = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), $filter, 0, $json, $modeCollectFe, $htmlElementNameIdZero, $storeUse);
} }
$htmlSip = $this->buildHiddenSip($json); $htmlSip = $this->buildHiddenSip($json);
...@@ -303,7 +316,7 @@ abstract class AbstractBuildForm { ...@@ -303,7 +316,7 @@ abstract class AbstractBuildForm {
* @throws \qfq\UserFormException * @throws \qfq\UserFormException
*/ */
public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json, public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, &$json,
$modeCollectFe = FLAG_DYNAMIC_UPDATE, $htmlElementNameIdZero = false) { $modeCollectFe = FLAG_DYNAMIC_UPDATE, $htmlElementNameIdZero = false, $storeUse = STORE_USE_DEFAULT) {
$html = ''; $html = '';
// get current data record // get current data record
...@@ -330,8 +343,11 @@ abstract class AbstractBuildForm { ...@@ -330,8 +343,11 @@ abstract class AbstractBuildForm {
$evaluate = new Evaluate($this->store, $this->db); $evaluate = new Evaluate($this->store, $this->db);
$formElement = $evaluate->parseArray($fe, $debugStack); $formElement = $evaluate->parseArray($fe, $debugStack);
// Some Defaults
$formElement = Support::setFeDefaults($formElement);
// Get default value // Get default value
$value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], STORE_USE_DEFAULT, $value = ($formElement['value'] === '') ? $this->store->getVar($formElement['name'], $storeUse,
$formElement['checkType']) : $formElement['value']; $formElement['checkType']) : $formElement['value'];
// Typically: $htmlElementNameIdZero = true // Typically: $htmlElementNameIdZero = true
...@@ -544,6 +560,27 @@ abstract class AbstractBuildForm { ...@@ -544,6 +560,27 @@ abstract class AbstractBuildForm {
// MIN( $formElement['maxLength'], tabledefinition) // MIN( $formElement['maxLength'], tabledefinition)
$maxLength = $this->getColumnSize($formElement['name']); $maxLength = $this->getColumnSize($formElement['name']);
switch ($formElement['type']) {
case 'date':
$feMaxLength = 10;
break;
case 'datetime':
$feMaxLength = 19;
break;
case 'time':
$feMaxLength = 8;
break;
default:
$feMaxLength = false;
break;
}
// In case the underlying tablecolumn is not of type date/time, the $maxLength might be to high: correct
if ($feMaxLength !== false && $maxLength !== false && $feMaxLength < $maxLength) {
$maxLength = $feMaxLength;
}
// date/datetime
if ($maxLength !== false) { if ($maxLength !== false) {
if (is_numeric($formElement['maxLength'])) { if (is_numeric($formElement['maxLength'])) {
if ($formElement['maxLength'] > $maxLength) { if ($formElement['maxLength'] > $maxLength) {
...@@ -559,14 +596,25 @@ abstract class AbstractBuildForm { ...@@ -559,14 +596,25 @@ abstract class AbstractBuildForm {
* Get column spec from tabledefinition and parse size of it. If nothing defined, return false. * Get column spec from tabledefinition and parse size of it. If nothing defined, return false.
* *
* @param $column * @param $column
* @return bool|int * @return bool|int a) 'false' if there is no length definition, b) length definition, c) date|time|datetime|timestamp use hardcoded length
*/ */
private function getColumnSize($column) { private function getColumnSize($column) {
$matches = array(); $matches = array();
$typeSpec = $this->store->getVar($column, STORE_TABLE_COLUMN_TYPES); $typeSpec = $this->store->getVar($column, STORE_TABLE_COLUMN_TYPES);
switch ($typeSpec) {
case 'date': // yyyy-mm-dd
return 10;
case 'datetime': // yyyy-mm-dd hh:mm:ss
case 'timestamp': // yyyy-mm-dd hh:mm:ss
return 19;
case 'time': // hh:mm:ss
return 8;
default:
break;
}
// e.g.: string(64), enum('yes','no') // e.g.: string(64) >> 64, enum('yes','no') >> false
if (1 === preg_match('/\((.+)\)/', $typeSpec, $matches)) { if (1 === preg_match('/\((.+)\)/', $typeSpec, $matches)) {
if (is_numeric($matches[1])) if (is_numeric($matches[1]))
return $matches[1]; return $matches[1];
...@@ -1456,16 +1504,153 @@ abstract class AbstractBuildForm { ...@@ -1456,16 +1504,153 @@ abstract class AbstractBuildForm {
} }
/** /**
* Build Date JQW element. * Builds HTML 'input' element.
* Format: <input name="$htmlFormElementId" <type="email|input|password|url" [autocomplete="autocomplete"] [autofocus="autofocus"]
* [maxlength="$maxLength"] [placeholder="$placeholder"] [size="$size"] [min="$min"] [max="$max"]
* [pattern="$pattern"] [readonly="readonly"] [required="required"] [disabled="disabled"] value="$value">
*
* *
* @param array $formElement * @param array $formElement
* @param $htmlFormElementId * @param $htmlFormElementId
* @param $value * @param $value
* @return string
* @throws UserFormException * @throws UserFormException
*/ */
public function buildDateJQW(array $formElement, $htmlFormElementId, $value) { public function builddateJQW(array $formElement, $htmlFormElementId, $value, &$json) {
// TODO: implement $textarea = '';
throw new UserFormException("Not implemented yet: buildDateJQW()", ERROR_NOT_IMPLEMENTED);
$attribute = Support::doAttribute('name', $htmlFormElementId);
$htmlTag = '<input';
$this->adjustMaxLength($formElement);
// Get date format
if (!isset($formElement['dateFormat'])) {
$formElement['dateFormat'] = $this->store->getVar(SYSTEM_DATE_FORMAT, STORE_SYSTEM);
}
// Format date
$value = Support::convertDateTime($value, $formElement[FE_DATE_FORMAT], $formElement[FE_SHOW_ZERO], 0, $formElement[FE_SHOW_SECONDS]);
// <input>
if ($formElement['maxLength'] > 0) {
// crop string only if it's not empty (substr returns false on empty strings)
if ($value !== '')
$value = substr($value, 0, $formElement['maxLength']);
// 'maxLength' needs an upper 'L': naming convention for DB tables!
$attribute .= $this->getAttributeList($formElement, ['type', 'size', 'maxLength']);
$attribute .= Support::doAttribute('value', htmlentities($value), false);
}
$attribute .= $this->getAttributeList($formElement, ['autocomplete', 'autofocus', 'placeholder']);
$attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
$attribute .= Support::doAttribute('title', $formElement['tooltip']);
$attribute .= $this->getInputCheckPattern($formElement['checkType'], $formElement['checkPattern']);
$attribute .= $this->getAttributeMode($formElement);
$json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement['mode']);
return "$htmlTag $attribute>$textarea";
}
/**
* Builds HTML 'input' element.
* Format: <input name="$htmlFormElementId" <type="date" [autocomplete="autocomplete"] [autofocus="autofocus"]
* [maxlength="$maxLength"] [placeholder="$placeholder"] [size="$size"] [min="$min"] [max="$max"]
* [pattern="$pattern"] [readonly="readonly"] [required="required"] [disabled="disabled"] value="$value">
*
*
* @param array $formElement
* @param $htmlFormElementId
* @param $value
* @param $json
* @return string
* @throws UserFormException
*/
public function buildDateTime(array $formElement, $htmlFormElementId, $value, &$json) {
$attribute = Support::doAttribute('name', $htmlFormElementId);
$arrMinMax = null;
$this->adjustMaxLength($formElement);
$showTime = ($formElement['type'] == 'time' || $formElement['type'] == 'datetime') ? 1 : 0;
$value = Support::convertDateTime($value, $formElement[FE_DATE_FORMAT], $formElement[FE_SHOW_ZERO], $showTime, $formElement[FE_SHOW_SECONDS]);
$tmpPattern = $formElement['checkPattern'];
$formElement['checkPattern'] = Support::dateTimeRegexp($formElement['type'], $formElement['dateFormat']);
switch ($formElement['checkType']) {
case 'pattern':
$formElement['checkPattern'] = $tmpPattern;
break;
case 'min|max date':
$arrMinMax = explode('|', $formElement['checkPattern'], 2);
if (count($arrMinMax) != 2) {
throw new UserFormException('Missing min|max definition', ERROR_MISSING_MIN_MAX);
}
break;
case 'all':
case 'alnumx':
$formElement['checkType'] = 'pattern';
break;
default:
throw new UserFormException("Checktype not applicable for date/time: '" . $formElement['checkType'] . "'", ERROR_NOT_APPLICABLE);
}
// truncate if necessary
if ($value != '') {
$value = substr($value, 0, $formElement['maxLength']);
}
$type = $formElement['type'];
if ($type === 'datetime')
$type = 'datetime-local';
$attribute .= Support::doAttribute('type', $type);
// 'maxLength' needs an upper 'L': naming convention for DB tables!
$attribute .= $this->getAttributeList($formElement, ['size', 'maxLength']);
$attribute .= Support::doAttribute('value', htmlentities($value), false);
if ($formElement['placeholder'] == '') {
$timePattern = ($formElement[FE_SHOW_SECONDS] == 1) ? 'hh:mm:ss' : 'hh:mm';
switch ($formElement['type']) {
case 'date':
$placeholder = $formElement['dateFormat'];
break;
case 'datetime':
$placeholder = $formElement['dateFormat'] . ' ' . $timePattern;
break;
case 'time':
$placeholder = $timePattern;
break;
default:
throw new UserFormException("Unexpected Formelement type: '" . $formElement['type'] . "'", ERROR_FORMELEMENT_TYPE);
}
$formElement['placeholder'] = $placeholder;
}
$attribute .= $this->getAttributeList($formElement, ['autocomplete', 'autofocus', 'placeholder']);
$attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
$attribute .= Support::doAttribute('title', $formElement['tooltip']);
$attribute .= $this->getInputCheckPattern($formElement['checkType'], $formElement['checkPattern']);
if (is_array($arrMinMax)) {
$attribute .= Support::doAttribute('min', $arrMinMax[0]);
$attribute .= Support::doAttribute('max', $arrMinMax[1]);
}
$attribute .= $this->getAttributeMode($formElement);
$json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement['mode']);
return "<input $attribute>";
} }
/** /**
......
...@@ -130,6 +130,9 @@ const ERROR_FORM_NOT_FOUND = 1052; ...@@ -130,6 +130,9 @@ const ERROR_FORM_NOT_FOUND = 1052;
const ERROR_DATE_TIME_FORMAT_NOT_RECOGNISED = 1053; const ERROR_DATE_TIME_FORMAT_NOT_RECOGNISED = 1053;
const ERROR_SANATIZE_INVALID_VALUE = 1054; const ERROR_SANATIZE_INVALID_VALUE = 1054;
const ERROR_REQUIRED_VALUE_EMPTY = 1055; const ERROR_REQUIRED_VALUE_EMPTY = 1055;
const ERROR_DATE_UNEXPECTED_FORMAT = 1056;
const ERROR_NOT_APPLICABLE = 1057;
const ERROR_FORMELEMENT_TYPE = 1058;
// Store // Store
const ERROR_STORE_VALUE_ALREADY_CODPIED = 1100; const ERROR_STORE_VALUE_ALREADY_CODPIED = 1100;
...@@ -236,6 +239,7 @@ const SYSTEM_DB_NAME_TEST = 'DB_NAME_TEST'; ...@@ -236,6 +239,7 @@ const SYSTEM_DB_NAME_TEST = 'DB_NAME_TEST';
const SYSTEM_SESSION_NAME = 'SESSION_NAME'; const SYSTEM_SESSION_NAME = 'SESSION_NAME';
const SYSTEM_SQL_LOG = 'SQL_LOG'; // Logging to file const SYSTEM_SQL_LOG = 'SQL_LOG'; // Logging to file
const SYSTEM_SQL_LOG_MODE = 'SQL_LOG_MODE'; // Mode, which statements to log. const SYSTEM_SQL_LOG_MODE = 'SQL_LOG_MODE'; // Mode, which statements to log.
const SYSTEM_DATE_FORMAT = 'DATE_FORMAT';
const SYSTEM_SHOW_DEBUG_INFO = 'SHOW_DEBUG_INFO'; const SYSTEM_SHOW_DEBUG_INFO = 'SHOW_DEBUG_INFO';
const SYSTEM_CSS_LINK_CLASS_INTERNAL = 'CSS_LINK_CLASS_INTERNAL'; const SYSTEM_CSS_LINK_CLASS_INTERNAL = 'CSS_LINK_CLASS_INTERNAL';
...@@ -341,6 +345,14 @@ const FE_MODE_REQUIRED = 'required'; ...@@ -341,6 +345,14 @@ const FE_MODE_REQUIRED = 'required';
const FE_MODE_LOCK = 'lock'; const FE_MODE_LOCK = 'lock';
const FE_MODE_DISABLED = 'disabled'; const FE_MODE_DISABLED = 'disabled';
// FormElement columns: real
const FE_TYPE = 'type';
// FormElement columns: via parameter field
const FE_DATE_FORMAT = 'dateFormat'; // value: FORMAT_DATE_INTERNATIONAL | FORMAT_DATE_GERMAN
const FE_SHOW_SECONDS = 'showSeconds'; // value: 0|1
const FE_SHOW_ZERO = 'showZero'; // value: 0|1
// SUPPORT // SUPPORT
const PARAM_T3_ALL = 't3 all'; const PARAM_T3_ALL = 't3 all';
const PARAM_T3_NO_ID = "t3 no id"; const PARAM_T3_NO_ID = "t3 no id";
...@@ -354,6 +366,11 @@ const QUERY_TYPE_INSERT = 'type: insert'; ...@@ -354,6 +366,11 @@ const QUERY_TYPE_INSERT = 'type: insert';
const QUERY_TYPE_UPDATE = 'type: update,replace,delete'; const QUERY_TYPE_UPDATE = 'type: update,replace,delete';
//Regexp //Regexp
const REGEXP_DATE_INT = '^\d{4}-\d{2}-\d{2}$'; //const REGEXP_DATE_INT = '^\d{4}-\d{2}-\d{2}$';
const REGEXP_DATE_GER = '^\d{1,2}\.\d{1,2}\.\d{2}(\d{2})?$'; //const REGEXP_DATE_GER = '^\d{1,2}\.\d{1,2}\.\d{2}(\d{2})?$';
const REGEXP_TIME = '^\d{1,2}:\d{1,2}(:\d{1,2})?$'; //const REGEXP_TIME = '^\d{1,2}:\d{1,2}(:\d{1,2})?$';
\ No newline at end of file
// Date/ DateTime formats
const FORMAT_DATE_INTERNATIONAL = 'yyyy-mm-dd';
const FORMAT_DATE_GERMAN = 'dd.mm.yyyy';
...@@ -98,6 +98,8 @@ class Save { ...@@ -98,6 +98,8 @@ class Save {
if (isset($formValues[$column])) { if (isset($formValues[$column])) {
$newValues[$column] = $formValues[$column]; $newValues[$column] = $formValues[$column];
} else {
$newValues[$column] = '';
} }
} }
......
...@@ -60,14 +60,14 @@ class Sanitize { ...@@ -60,14 +60,14 @@ class Sanitize {
// a) der Value verletzt die Datumsgrenzen // a) der Value verletzt die Datumsgrenzen
// b) die Definition der Grenzen ist buggy // b) die Definition der Grenzen ist buggy
// try { // try {
$valueCompare = Support::dateTime2mysql($value); $valueCompare = Support::dateTimeGermanToInternational($value);
// } catch (UserFormException $e) { // } catch (UserFormException $e) {
// throw new UserFormException("Date or time not recognized '" . $value . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE); // throw new UserFormException("Date or time not recognized '" . $value . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE);
// } // }
// try { // try {
$minMax[0] = Support::dateTime2mysql($minMax[0]); $minMax[0] = Support::dateTimeGermanToInternational($minMax[0]);
$minMax[1] = Support::dateTime2mysql($minMax[1]); $minMax[1] = Support::dateTimeGermanToInternational($minMax[1]);
// } catch (UserFormException $e) { // } catch (UserFormException $e) {
// throw new UserFormException("Date or time of min|max definition not recognized '" . $patternOrRange . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE); // throw new UserFormException("Date or time of min|max definition not recognized '" . $patternOrRange . "' - " . $e->formatMessage(), ERROR_SANATIZE_INVALID_VALUE);
// } // }
......
...@@ -130,7 +130,7 @@ class Support { ...@@ -130,7 +130,7 @@ class Support {
} }
/** /**
* Converts a dateTime String to the english format: * Converts a dateTime String to the international format:
* 1.2.79 > 1979-02-01 00:00:00 * 1.2.79 > 1979-02-01 00:00:00
* 01.02.13 3:24 > 1979-02-01 03:24:00 * 01.02.13 3:24 > 1979-02-01 03:24:00
* 1.2.1979 14:21:5 > 1979-02-01 14:21:05 * 1.2.1979 14:21:5 > 1979-02-01 14:21:05
...@@ -139,7 +139,7 @@ class Support { ...@@ -139,7 +139,7 @@ class Support {
* @return string * @return string
* @throws UserFormException * @throws UserFormException
*/ */
public static function dateTime2mysql($dateTimeString) { public static function dateTimeGermanToInternational($dateTimeString) {
$dateRaw = ''; $dateRaw = '';
$timeRaw = ''; $timeRaw = '';
...@@ -175,11 +175,12 @@ class Support { ...@@ -175,11 +175,12 @@ class Support {
$date = '0000-00-00'; $date = '0000-00-00';
} else { } else {
// International format: YYYY-MM-DD // International format: YYYY-MM-DD
if (preg_match("/" . REGEXP_DATE_INT . "/", $dateRaw) === 1) {
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $dateRaw) === 1) {
$date = $dateRaw; $date = $dateRaw;
// German format: 1.1.01 - 11.12.1234 // German format: 1.1.01 - 11.12.1234
} elseif (preg_match("/" . REGEXP_DATE_GER . "/", $dateRaw) === 1) { } elseif (preg_match('/^\d{1,2}\.\d{1,2}\.\d{2}(\d{2})?$/', $dateRaw) === 1) {
$tmpArr = explode('.', $dateRaw); $tmpArr = explode('.', $dateRaw);
if ($tmpArr[2