Commit 9f0da3ae authored by Rafael Ostertag's avatar Rafael Ostertag
Browse files

Merge remote-tracking branch 'origin/crose_work' into raos_work

Conflicts:
	CODING.md
parents 59ee0179 b98b5926
......@@ -157,6 +157,7 @@ New Button
* Client does not save the modified record.
* Client stays on current page.
File Handling
-------------
* No previous uploaded file present
......@@ -172,6 +173,31 @@ File Handling
1. File delete button gets disabled and hidden
1. Browse button gets enabled and displayed
Formelement type: DATE / DATETIME / TIME
----------------------------------------
* Available Formats:
* 'yyyy-mm-dd' = FORMAT_DATE_INTERNATIONAL.
* 'dd.mm.yyyy' = FORMAT_DATE_GERMAN.
* The 'DATE_FORMAT' can be specified systemwide in `config.ini`
* The default format is FORMAT_DATE_INTERNATIONAL.
* Optional: 'dateFormat' can be specified per form element in `form.parameter` - this overwrites 'systemwide'.
* If there is no placeholder defined on the form element, the defined dateFormat is shown as placeholder.
* Browser:
* checks the input with a system regexp.
* regexp might be user defined. If given, do not use system regexp!
* No min/max check.
* Server:
* check with system wirde regexp
* regexp might be user defined. If given, do not use system regexp!
* Do min/max check.
* MySQL data: 1000-01-01 - 9999-12-31 and 0000-00-00
* MySQL time: 00:00:00 - 23:59:59
* datetime format: 'DATE TIME'
Debug / Log / Errormessages
===========================
......
......@@ -38,20 +38,21 @@ Setup
page.includeCSS {
file1 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap.min.css
file2 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-theme.min.css
file3 = typo3conf/ext/qfq/Resources/Public/Css/jqx.base.css
file4 = typo3conf/ext/qfq/Resources/Public/Css/jqx.darkblue.css
file5 = typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css
file1 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap.min.css
file2 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-theme.min.css
file3 = typo3conf/ext/qfq/Resources/Public/Css/jqx.base.css
file4 = typo3conf/ext/qfq/Resources/Public/Css/jqx.darkblue.css
file5 = typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css
}
page.includeJS {
file1 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.min.js
file2 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap.min.js
file3 = typo3conf/ext/qfq/Resources/Public/JavaScript/jqx-all.js
file4 = typo3conf/ext/qfq/Resources/Public/JavaScript/EventEmitter.min.js
file5 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.min.js
file1 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.min.js
file2 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap.min.js
file3 = typo3conf/ext/qfq/Resources/Public/JavaScript/validator.min.js
file4 = typo3conf/ext/qfq/Resources/Public/JavaScript/jqx-all.js
file5 = typo3conf/ext/qfq/Resources/Public/JavaScript/EventEmitter.min.js
file6 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.debug.js
}
FormEditor
......@@ -101,6 +102,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 |
+------------------------+----------------------------------+----------------------------------------------------------------------------+
| DATE_FORMAT | DATE_FORMAT= yyyy-mm-dd | Possible options: yyyy-mm-dd, dd.mm.yyyy |
+------------------------+----------------------------------+----------------------------------------------------------------------------+
Example: *<ext_dir>/config.ini*
......
......@@ -507,9 +507,10 @@ Class: Native
|class | enum('native', 'action', | Details below. |
| | 'container') | |
+--------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|type | enum('checkbox', 'dateJQW', 'datetimeJQW', 'gridJQW', 'hidden', 'text', 'note', 'password', 'radio', 'select', 'subrecord', |
| | 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'before_load', 'before_save', 'before_insert', 'before_update', |
| | 'before_delete', 'after_load', 'after_save', 'after_insert', 'after_update', 'after_delete', 'feGroup', 'sendmail') |
|type | enum('checkbox', 'date', 'time', 'datetime', 'dateJQW', 'datetimeJQW', 'gridJQW', 'hidden', 'text', 'note', 'password', |
| | 'radio', 'select', 'subrecord', 'textarea', 'timeJQW', 'upload', 'fieldset', 'pill', 'before_load', 'before_save', |
| | 'before_insert', 'before_update', 'before_delete', 'after_load', 'after_save', 'after_insert', 'after_update', 'after_delete', |
| | 'feGroup', 'sendmail') |
+--------------+-----------------------------+---------------------------------------------------------------------------------------------------+
|checkType | enum('min|max', 'pattern', | |
| | 'number', 'email') | |
......@@ -685,9 +686,19 @@ Checkboxes can be rendered in mode:
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
^^^^^^^^^^^^^^
* 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
^^^^^^^^^^^^
......@@ -807,6 +818,11 @@ Typically not used. Useful if user wishes an explicit 'Submit' Button.
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
^^^^^^^^^^^^
......
......@@ -20,3 +20,6 @@ CSS_LINK_CLASS_EXTERNAL = external
; QFQ with own Bootstrap: 'container'. QFQ already nested in Bootstrap of mainpage: <empty>
CSS_CLASS_QFQ_CONTAINER =
; yyyy-mm-dd, dd.mm.yyyy
DATE_FORMAT = yyyy-mm-dd
<?php
/**
* Created by PhpStorm.
* User: crose
* Date: 4/25/16
* Time: 8:02 PM
*/
$answer = array();
$answer[API_MESSAGE] = '';
$answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
try {
$upload = new \qfq\File();
$upload->process();
$answer[API_MESSAGE] = 'upload: success';
$answer[API_REDIRECT] = API_ANSWER_REDIRECT_NO;
$answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS;
} catch (qfq\UserFormException $e) {
$answer[API_MESSAGE] = $e->formatMessage();
} catch (qfq\CodeException $e) {
$answer[API_MESSAGE] = $e->formatMessage();
} catch (qfq\DbException $e) {
$answer[API_MESSAGE] = $e->formatMessage();
} catch (\Exception $e) {
$answer[API_MESSAGE] = "Generic Exception: " . $e->getMessage();
}
header("Content-Type: application/json");
echo json_encode($answer);
[Mon, 29 Feb 2016 15:32:39 +0100][SELECT * FROM Form AS f WHERE f.name LIKE 'formElement' AND f.deleted='no']
[Mon, 29 Feb 2016 15:32:39 +0100][Get rows: 1]
[Mon, 29 Feb 2016 15:32:39 +0100][SELECT id, " / ", title FROM Form WHERE id = 0]
[Mon, 29 Feb 2016 15:32:39 +0100][Get rows: 0]
[Mon, 29 Feb 2016 15:32:39 +0100][SELECT *, 'no' AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = '2' AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, 'action' ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id]
[Mon, 29 Feb 2016 15:32:39 +0100][Get rows: 0]
[Mon, 29 Feb 2016 15:32:39 +0100][SELECT *, 'no' AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = '2' AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, 'native' ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id]
[Mon, 29 Feb 2016 15:32:39 +0100][Get rows: 28]
[Mon, 29 Feb 2016 15:32:39 +0100][SHOW FIELDS FROM `FormElement`]
[Mon, 29 Feb 2016 15:32:39 +0100][Get rows: 29]
[Mon, 29 Feb 2016 15:32:39 +0100][UPDATE `FormElement` SET `formId` = '1', `feIdContainer` = '1', `enabled` = 'yes', `name` = 'id1', `label` = 'id', `mode` = 'readonly', `class` = 'native', `type` = 'text', `checkType` = '', `checkPattern` = '', `onChange` = '', `ord` = '100', `tabindex` = '0', `size` = '10', `note` = '', `tooltip` = '', `placeholder` = '', `value` = '', `sql1` = '', `parameter` = '', `clientJs` = '', `feGroup` = '', `debug` = 'no', `deleted` = 'no', `modified` = '2016-02-29 15:17:28', `created` = '0000-00-00 00:00:00' WHERE id = '6']
[Mon, 29 Feb 2016 15:32:39 +0100][Affected rows: 1]
[Mon, 29 Feb 2016 15:32:52 +0100][SELECT * FROM Form AS f WHERE f.name LIKE 'formElement' AND f.deleted='no']
[Mon, 29 Feb 2016 15:32:52 +0100][Get rows: 1]
[Mon, 29 Feb 2016 15:32:52 +0100][SELECT id, " / ", title FROM Form WHERE id = 0]
[Mon, 29 Feb 2016 15:32:52 +0100][Get rows: 0]
[Mon, 29 Feb 2016 15:32:52 +0100][SELECT *, 'no' AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = '2' AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, 'action' ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id]
[Mon, 29 Feb 2016 15:32:52 +0100][Get rows: 0]
[Mon, 29 Feb 2016 15:32:52 +0100][SELECT *, 'no' AS 'nestedInFieldSet' FROM FormElement AS fe WHERE fe.formId = '2' AND fe.deleted = 'no' AND FIND_IN_SET(fe.class, 'native' ) AND fe.enabled='yes' ORDER BY fe.ord, fe.id]
[Mon, 29 Feb 2016 15:32:52 +0100][Get rows: 28]
[Mon, 29 Feb 2016 15:32:52 +0100][SHOW FIELDS FROM `FormElement`]
[Mon, 29 Feb 2016 15:32:52 +0100][Get rows: 29]
[Mon, 29 Feb 2016 15:32:52 +0100][UPDATE `FormElement` SET `formId` = '1', `feIdContainer` = '1', `enabled` = 'yes', `name` = 'id', `label` = 'id', `mode` = 'readonly', `class` = 'native', `type` = 'text', `checkType` = '', `checkPattern` = '', `onChange` = '', `ord` = '100', `tabindex` = '0', `size` = '10', `note` = '', `tooltip` = '', `placeholder` = '', `value` = '', `sql1` = '', `parameter` = '', `clientJs` = '', `feGroup` = '', `debug` = 'no', `deleted` = 'no', `modified` = '2016-02-29 15:17:28', `created` = '0000-00-00 00:00:00' WHERE id = '6']
[Mon, 29 Feb 2016 15:32:52 +0100][Affected rows: 1]
......@@ -5,12 +5,13 @@
* Date: 1/6/16
* Time: 8:02 PM
*/
namespace qfq;
use qfq;
use qfq\Store;
use qfq\UserFormException;
use qfq\OnArray;
use qfq\UserFormException;
require_once(__DIR__ . '/../qfq/store/Store.php');
require_once(__DIR__ . '/../qfq/Constants.php');
......@@ -66,12 +67,15 @@ abstract class AbstractBuildForm {
$this->buildElementFunctionName = [
'checkbox' => 'Checkbox',
'date' => 'DateTime',
'datetime' => 'DateTime',
'dateJQW' => 'DateJQW',
'datetimeJQW' => 'DateJQW',
'email' => 'Input',
'gridJQW' => 'GridJQW',
'hidden' => 'Hidden',
'text' => 'Input',
'time' => 'DateTime',
'note' => 'Note',
'password' => 'Input',
'radio' => 'Radio',
......@@ -84,12 +88,15 @@ abstract class AbstractBuildForm {
$this->buildRowName = [
'checkbox' => 'Native',
'date' => 'Native',
'datetime' => 'Native',
'dateJQW' => 'Native',
'datetimeJQW' => 'Native',
'email' => 'Native',
'gridJQW' => 'Native',
'hidden' => 'Native',
'text' => 'Native',
'time' => 'Native',
'note' => 'Native',
'password' => 'Native',
'radio' => 'Native',
......@@ -124,7 +131,14 @@ abstract class AbstractBuildForm {
$htmlSubrecords = '';
$htmlElements = '';
$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>
if ($mode === FORM_LOAD) {
......@@ -145,7 +159,7 @@ abstract class AbstractBuildForm {
$json[] = $jsonTmp;
}
} 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);
......@@ -303,7 +317,7 @@ abstract class AbstractBuildForm {
* @throws \qfq\UserFormException
*/
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 = '';
// get current data record
......@@ -330,8 +344,11 @@ abstract class AbstractBuildForm {
$evaluate = new Evaluate($this->store, $this->db);
$formElement = $evaluate->parseArray($fe, $debugStack);
// Some Defaults
$formElement = Support::setFeDefaults($formElement);
// 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'];
// Typically: $htmlElementNameIdZero = true
......@@ -369,7 +386,7 @@ abstract class AbstractBuildForm {
// Construct Marshaller Name: buildRow
$buildRowName = 'buildRow' . $this->buildRowName[$formElement['type']];
$html .= $this->$buildRowName($formElement, $elementHtml);
$html .= $this->$buildRowName($formElement, $elementHtml, $htmlFormElementId);
// break;
}
......@@ -457,23 +474,26 @@ abstract class AbstractBuildForm {
return $url;
}
abstract public function buildRowNative($formElement, $elementHtml);
abstract public function buildRowNative(array $formElement, $htmlElement, $htmlFormElementId);
abstract public function buildRowPill($formElement, $elementHtml);
abstract public function buildRowPill(array $formElement, $elementHtml);
abstract public function buildRowFieldset($formElement, $elementHtml);
abstract public function buildRowFieldset(array $formElement, $elementHtml);
abstract public function buildRowSubrecord($formElement, $elementHtml);
abstract public function buildRowSubrecord(array $formElement, $elementHtml);
/**
* Builds a label, typically for an html-'<input>'-element.
*
* @param array $htmlFormElementId
* @param $label
* @param string $htmlFormElementId
* @param string $label
* @return string
*/
public function buildLabel($htmlFormElementId, $label) {
$html = '<label for="' . $htmlFormElementId . '">' . $label . '</label>';
$attributes = Support::doAttribute('for', $htmlFormElementId);
$attributes .= Support::doAttribute('class', 'control-label');
$html = Support::wrapTag("<label $attributes>", $label);
return $html;
}
......@@ -495,6 +515,7 @@ abstract class AbstractBuildForm {
$textarea = '';
$attribute = Support::doAttribute('name', $htmlFormElementId);
$attribute .= Support::doAttribute('class', 'form-control');
// Check for input type 'textarea'
$colsRows = explode(',', $formElement['size'], 2);
......@@ -532,7 +553,7 @@ abstract class AbstractBuildForm {
$json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement['mode']);
return "$htmlTag $attribute>$textarea";
return "$htmlTag $attribute>$textarea" . $this->getHelpBlock();
}
......@@ -544,6 +565,27 @@ abstract class AbstractBuildForm {
// MIN( $formElement['maxLength'], tabledefinition)
$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 (is_numeric($formElement['maxLength'])) {
if ($formElement['maxLength'] > $maxLength) {
......@@ -559,14 +601,25 @@ abstract class AbstractBuildForm {
* Get column spec from tabledefinition and parse size of it. If nothing defined, return false.
*
* @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) {
$matches = array();
$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 (is_numeric($matches[1]))
return $matches[1];
......@@ -679,6 +732,13 @@ abstract class AbstractBuildForm {
return $attribute;
}
/**
* @return string
*/
private function getHelpBlock() {
return '<div class="help-block with-errors"></div>';
}
/**
* Builds HTML 'checkbox' element.
*
......@@ -1085,6 +1145,7 @@ abstract class AbstractBuildForm {
$attribute = $this->getAttributeMode($formElement);
$attribute .= Support::doAttribute('name', $htmlFormElementId);
$attribute .= Support::doAttribute('class', 'form-control');
$attribute .= Support::doAttribute('title', $formElement['tooltip']);
$attribute .= $this->getAttributeList($formElement, ['autofocus']);
$attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
......@@ -1118,7 +1179,7 @@ abstract class AbstractBuildForm {
$json = $this->getJsonElementUpdate($htmlFormElementId, $jsonValues, $formElement['mode']);
return '<select ' . $attribute . '>' . $option . '</select>';
return '<select ' . $attribute . '>' . $option . '</select>' . $this->getHelpBlock();
}
/**
......@@ -1442,30 +1503,194 @@ abstract class AbstractBuildForm {
* @throws UserFormException
*/
public function buildFile(array $formElement, $htmlFormElementId, $value, &$json) {
$attribute = '';
$attribute = $this->getAttributeMode($formElement);
$sip = $this->store->getVar(SIP_SIP, STORE_SIP);
$value = basename($value); // Strip directories
$attribute .= Support::doAttribute('name', $htmlFormElementId);
// $attribute .= Support::doAttribute('class', 'form-control');
$attribute .= Support::doAttribute('type', 'file');
$attribute .= Support::doAttribute('title', $formElement['tooltip']);
$attribute .= Support::doAttribute('name', $htmlFormElementId);
$attribute .= $this->getAttributeList($formElement, ['autofocus', 'accept']);
$attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
if ($value === '') {
$textDeleteClass = 'hidden';
$uploadClass = '';
} else {
$textDeleteClass = '';
$uploadClass = 'hidden';
$formElement['mode'] = 'disabled';
}
$attribute .= $this->getAttributeMode($formElement);
$attribute .= Support::doAttribute('class', $uploadClass, true);
$htmlInputFile = '<input ' . $attribute . '>' . $this->getHelpBlock();
$deleteButton = Support::wrapTag("<button class='delete-file' data-sip='$sip' name='trash-$htmlFormElementId'>", $this->symbol[SYMBOL_DELETE]);
$htmlFilename = Support::wrapTag("<span class='uploaded-file-name'>", $value, false);
$htmlTextDelete = Support::wrapTag("<div class='uploaded-file $textDeleteClass'>", $htmlFilename . ' ' . $deleteButton);
// <button type="button" class="file-delete" data-sip="571d1fc9e6974"><span class="glyphicon glyphicon-trash"></span></button>
$json = $this->getJsonElementUpdate($htmlFormElementId, $value, $formElement['mode']);
return '<input ' . $attribute . '>';
return $htmlTextDelete . $htmlInputFile;
}
/**
* 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 $htmlFormElementId
* @param $value
* @return string
* @throws UserFormException
*/
public function buildDateJQW(array $formElement, $htmlFormElementId, $value) {
// TODO: implement
throw new UserFormException("Not implemented yet: buildDateJQW()", ERROR_NOT_IMPLEMENTED);
public function builddateJQW(array $formElement, $htmlFormElementId, $value, &$json) {
$textarea = '';
$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);
$attribute .= Support::doAttribute('class', 'form-control');
$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 SANITIZE_ALLOW_PATTERN:
$formElement['checkPattern'] = $tmpPattern;
break;
case SANITIZE_ALLOW_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 SANITIZE_ALLOW_ALL:
case SANITIZE_ALLOW_ALNUMX:
case SANITIZE_ALLOW_ALLBUT:
$formElement['checkType'] = SANITIZE_ALLOW_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;