Commit 13d39fbe authored by Carsten  Rose's avatar Carsten Rose
Browse files

#2064: Input Elemente die als JSON response 'value=false' bekommen, zeigen 'false' an.

#3253: STORE_TYPO3: steht waehrend Update / Save nicht zur Verfuegung - wird aber benoetigt. Bsp: feUser, beUser, pageId, ...

Thought that problem of #2064 is based on #3253 - that was wrong.
#3253 implemented, but not heavily tested.

#2064: problem was that for a non existing tablecolumn, has been searched for a default value - which obviously does not exist. In AbstractBuildForm.php, Line 419, a check implemented if the current FormElement is an existing tablecolumn. If not, do not change the empty value.

FormAction.php, FillStoreForm.php, Store.php, QuickFormQuery.php, Save.php: Refactor setVarArray() to setStore()

#3253
FillStoreForm.php: If there is no STORE_TYPO3, get the old values from SIP: CLIENT_TYPO3VARS.
Store.php: new function fillTypo3StoreFromSip(), copyT3VarstToSip()
parent a6b22ba2
......@@ -146,6 +146,7 @@ abstract class AbstractBuildForm {
public function process($mode, $htmlElementNameIdZero = false) {
$htmlHead = '';
$htmlTail = '';
$htmlT3vars = '';
$htmlSubrecords = '';
$htmlElements = '';
$json = array();
......@@ -169,7 +170,7 @@ abstract class AbstractBuildForm {
$parentRecords = $this->db->sql($this->formSpec['multiSql']);
foreach ($parentRecords as $row) {
$this->store->setVarArray($row, STORE_PARENT_RECORD, true);
$this->store->setStore($row, STORE_PARENT_RECORD, true);
$jsonTmp = array();
$htmlElements = $this->elements($row['_id'], $filter, 0, $jsonTmp, $modeCollectFe);
$json[] = $jsonTmp;
......@@ -181,13 +182,14 @@ abstract class AbstractBuildForm {
// <form>
if ($mode === FORM_LOAD) {
$htmlT3vars = $this->prepareT3VarsForSave();
$htmlTail = $this->tail();
$htmlSubrecords = $this->doSubrecords();
}
$htmlSip = $this->buildHiddenSip($json);
return ($mode === FORM_LOAD) ? $htmlHead . $htmlElements . $htmlSip . $htmlTail . $htmlSubrecords : $json;
return ($mode === FORM_LOAD) ? $htmlHead . $htmlElements . $htmlSip . $htmlT3vars . $htmlTail . $htmlSubrecords : $json;
}
/**
......@@ -354,7 +356,7 @@ abstract class AbstractBuildForm {
// get current data record
if ($recordId > 0 && $this->store->getVar('id', STORE_RECORD) === false) {
$row = $this->db->sql("SELECT * FROM " . $this->formSpec[F_TABLE_NAME] . " WHERE id = ?", ROW_EXPECT_1, array($recordId), "Form '" . $this->formSpec[F_NAME] . "' failed to load record '$recordId' from table '" . $this->formSpec[F_TABLE_NAME] . "'.");
$this->store->setVarArray($row, STORE_RECORD);
$this->store->setStore($row, STORE_RECORD);
}
$this->checkAutoFocus();
......@@ -397,9 +399,17 @@ abstract class AbstractBuildForm {
$name = (isset($formElement[FE_RETYPE_SOURCE_NAME])) ? $formElement[FE_RETYPE_SOURCE_NAME] : $formElement[FE_NAME];
// Get default value
$value = ($formElement[FE_VALUE] === '') ? $this->store->getVar($name, $storeUse,
$formElement['checkType']) : $formElement[FE_VALUE];
// $value = ($formElement[FE_VALUE] === '') ? $this->store->getVar($name, $storeUse,
// $formElement['checkType']) : $formElement[FE_VALUE];
$value = $formElement[FE_VALUE];
// If there is no value, check the default.
if ($value === '') {
// Only take the default, if the FE is a real tablecolumn.
if ($this->store->getVar($formElement[FE_NAME], STORE_RECORD) !== false) {
$value = $this->store->getVar($name, $storeUse, $formElement['checkType']);
}
}
// Typically: $htmlElementNameIdZero = true
// After Saving a record, staying on the form, the FormElements on the Client are still known as '<feName>:0'.
$htmlFormElementId = HelperFormElement::buildFormElementName($formElement[FE_NAME], ($htmlElementNameIdZero) ? 0 : $recordId);
......@@ -498,6 +508,31 @@ abstract class AbstractBuildForm {
abstract public function fillWrapLabelInputNote($label, $input, $note);
/**
* Copy a subset of current STORE_TYPO3 variables to SIP. Set a hidden form field to submit the assigned SIP to save/update.
*
* @throws CodeException
* @throws UserFormException
*/
private function prepareT3VarsForSave() {
$t3VarsSip = $this->store->copyT3VarsToSip();
return $this->buildNativeHidden(CLIENT_TYPO3VARS, $t3VarsSip);
}
/**
* Builds a real HTML hidden form element. Useful for checkboxes, Multiple-Select and Radios.
*
* @param $htmlFormElementId
* @param $value
* @return string
*/
public function buildNativeHidden($htmlFormElementId, $value) {
return '<input type="hidden" name="' . $htmlFormElementId . '" value="' . htmlentities($value) . '">';
}
abstract public function tail();
abstract public function doSubrecords();
......@@ -592,17 +627,6 @@ abstract class AbstractBuildForm {
}
}
/**
* Builds a real HTML hidden form element. Useful for checkboxes, Multiple-Select and Radios.
*
* @param $htmlFormElementId
* @param $value
* @return string
*/
public function buildNativeHidden($htmlFormElementId, $value) {
return '<input type="hidden" name="' . $htmlFormElementId . '" value="' . htmlentities($value) . '">';
}
/**
* Takes the current SIP ('form' and additional parameter), set SIP_RECORD_ID=0 and create a new 'NewRecordUrl'.
*
......@@ -2318,77 +2342,6 @@ abstract class AbstractBuildForm {
return $html;
}
/**
* Build real FormElements based on the current templateGroup FormElements in $this->feSpecNative.
* Take a templateGroup 'copy', if at least one of the elements is filled with a non default value.
* Stop filling elements if there are no further elements filled.
*
* @param int $max
* @param string $htmlDelete
* @param array $json
* @return string
* @throws CodeException
* @throws \qfq\UserFormException
*/
private function templateGroupCollectFilledElements($max, $htmlDelete, array &$json) {
$record = $this->store->getStore(STORE_RECORD); // current values
if($record===false || count($record)===0) {
return '';
}
$default = $this->store->getStore(STORE_TABLE_DEFAULT); // current defaults
$lastFilled = 0; // Marker if there is at least one element per copy who is filled.
$feSpecNativeCopy = array();
for($ii = 1; $ii < $max; $ii++) {
// Per copy, iterate over all templateGroup FormElements
foreach($this->feSpecNative as $fe) {
$columnName = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NAME]);
$fe[FE_LABEL] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_LABEL]);
$fe[FE_NOTE] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NOTE]);
if(isset($record[$columnName])) {
if($record[$columnName] != $default[$columnName]) {
$lastFilled = $ii;
}
} else {
throw new UserFormException("Not implemented: templateGroup FormElement-columns not found in primary table.", ERROR_NOT_IMPLEMENTED);
}
$fe[FE_NAME] = $columnName;
$feSpecNativeCopy[$ii-1][] = $fe; // Build array with current copy of templateGroup.
}
// Append $htmlDelete on the last element of all copies,, but not the first.
if($ii>1) {
// Count defined FormElements in the current templateGroup
$last = count($feSpecNativeCopy[$ii-1]) - 1;
// Append 'delete' Button at the note of the last element
$feSpecNativeCopy[$ii-1][$last][FE_NOTE] .= $htmlDelete;
}
}
// Nothing found: return
if(count($feSpecNativeCopy)==0){
return '';
}
$feSpecNativeSave = $this->feSpecNative;
$html = '';
for($ii=0; $ii<$lastFilled; $ii++) {
$this->feSpecNative = $feSpecNativeCopy[$ii];
$htmlCopy = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), FORM_ELEMENTS_NATIVE, 0, $json);
$htmlCopy = Support::wrapTag('<div class="qfq-line">', $htmlCopy);
$html .= $htmlCopy;
}
$this->feSpecNative = $feSpecNativeSave;
return $html;
}
/**
* Build a 'templateGroup'. Renders all assigned FormElements of the templateGroup.
* If there are already vlaues for the formElements, fill as much copies as values exist
......@@ -2497,6 +2450,77 @@ EOT;
}
/**
* Build real FormElements based on the current templateGroup FormElements in $this->feSpecNative.
* Take a templateGroup 'copy', if at least one of the elements is filled with a non default value.
* Stop filling elements if there are no further elements filled.
*
* @param int $max
* @param string $htmlDelete
* @param array $json
* @return string
* @throws CodeException
* @throws \qfq\UserFormException
*/
private function templateGroupCollectFilledElements($max, $htmlDelete, array &$json) {
$record = $this->store->getStore(STORE_RECORD); // current values
if ($record === false || count($record) === 0) {
return '';
}
$default = $this->store->getStore(STORE_TABLE_DEFAULT); // current defaults
$lastFilled = 0; // Marker if there is at least one element per copy who is filled.
$feSpecNativeCopy = array();
for ($ii = 1; $ii < $max; $ii++) {
// Per copy, iterate over all templateGroup FormElements
foreach ($this->feSpecNative as $fe) {
$columnName = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NAME]);
$fe[FE_LABEL] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_LABEL]);
$fe[FE_NOTE] = str_replace(FE_TEMPLATE_GROUP_NAME_PATTERN, $ii, $fe[FE_NOTE]);
if (isset($record[$columnName])) {
if ($record[$columnName] != $default[$columnName]) {
$lastFilled = $ii;
}
} else {
throw new UserFormException("Not implemented: templateGroup FormElement-columns not found in primary table.", ERROR_NOT_IMPLEMENTED);
}
$fe[FE_NAME] = $columnName;
$feSpecNativeCopy[$ii - 1][] = $fe; // Build array with current copy of templateGroup.
}
// Append $htmlDelete on the last element of all copies,, but not the first.
if ($ii > 1) {
// Count defined FormElements in the current templateGroup
$last = count($feSpecNativeCopy[$ii - 1]) - 1;
// Append 'delete' Button at the note of the last element
$feSpecNativeCopy[$ii - 1][$last][FE_NOTE] .= $htmlDelete;
}
}
// Nothing found: return
if (count($feSpecNativeCopy) == 0) {
return '';
}
$feSpecNativeSave = $this->feSpecNative;
$html = '';
for ($ii = 0; $ii < $lastFilled; $ii++) {
$this->feSpecNative = $feSpecNativeCopy[$ii];
$htmlCopy = $this->elements($this->store->getVar(SIP_RECORD_ID, STORE_SIP), FORM_ELEMENTS_NATIVE, 0, $json);
$htmlCopy = Support::wrapTag('<div class="qfq-line">', $htmlCopy);
$html .= $htmlCopy;
}
$this->feSpecNative = $feSpecNativeSave;
return $html;
}
abstract public function buildRowNative(array $formElement, $htmlElement, $htmlFormElementId);
......
......@@ -256,6 +256,7 @@ const CLIENT_UPLOAD_FE_NAME = 'name';
const CLIENT_SIP_FOR_FORM = '_sipForForm';
const CLIENT_FE_NAME = '_feName';
const CLIENT_TYPO3VARS = '_sipForTypo3Vars';
// ALL $_SERVER variables: http://php.net/manual/en/reserved.variables.server.php
// The following exist and might be the most used ones.
......@@ -277,6 +278,7 @@ const CLIENT_PHP_SELF = 'PHP_SELF';
// T3 Bodytext Keywords
const TYPO3_FORM = CLIENT_FORM;
const TYPO3_RECORD_ID = CLIENT_RECORD_ID;
const TYPO3_BE_USER_LOGGED_IN = 'beUser'; // 'yes' | 'no'
const TYPO3_FE_USER = 'feUser';
const TYPO3_FE_USER_UID = 'feUserUid';
const TYPO3_FE_USER_GROUP = 'feUserGroup';
......
......@@ -668,7 +668,7 @@ class QuickFormQuery {
private function fillStoreWithRecord($table, $recordId, $store = STORE_RECORD) {
if ($recordId !== false && $recordId > 0) {
$record = $this->db->sql("SELECT * FROM $table WHERE id = ?", ROW_EXPECT_1, [$recordId]);
$this->store->setVarArray($record, $store, true);
$this->store->setStore($record, $store, true);
}
}
......@@ -688,7 +688,7 @@ class QuickFormQuery {
}
$sipArray[SIP_RECORD_ID] = $recordId;
$this->store->setVarArray($sipArray, STORE_SIP, true);
$this->store->setStore($sipArray, STORE_SIP, true);
// Update SIP urlparam
store::getSipInstance()->updateSipToSession($sipArray);
......@@ -784,7 +784,7 @@ class QuickFormQuery {
// Overwrite SIP Store
$tmpParam[SIP_SIP] = $sip;
$this->store->setVarArray($tmpParam, STORE_SIP, true);
$this->store->setStore($tmpParam, STORE_SIP, true);
}
}
\ No newline at end of file
......@@ -60,7 +60,7 @@ class Save {
$parentRecords = $this->db->sql($this->formSpec['multiSql']);
foreach ($parentRecords as $row) {
$this->store->setVarArray($row, STORE_PARENT_RECORD, true);
$this->store->setStore($row, STORE_PARENT_RECORD, true);
$rc = $this->elements($row['_id']);
}
} else {
......
......@@ -129,7 +129,7 @@ class FormAction {
if ($recordId !== false && $recordId > 0) {
$record = $this->db->sql("SELECT * FROM $table WHERE id = ?", ROW_EXPECT_1, [$recordId]);
$this->store->setVarArray($record, STORE_RECORD, true);
$this->store->setStore($record, STORE_RECORD, true);
}
}
......
......@@ -48,6 +48,33 @@ class FillStoreForm {
}
/**
* Loads a minimal definition of FormElement of the form specified in SIP.
*
* @return array
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function loadFormElementsBasedOnSIP() {
$formName = $this->store->getVar(SIP_FORM, STORE_SIP);
// Preparation for Log, Debug
$this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM);
$feSpecNative = $this->db->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_EXPECT_GE_1, [$formName],
'Form or FormElements not found: ' . ERROR_FORM_NOT_FOUND);
HelperFormElement::explodeParameterInArrayElements($feSpecNative);
$feSpecTemplateGroup = $this->db->sql(SQL_FORM_ELEMENT_CONTAINER_TEMPLATE_GROUP, ROW_REGULAR, [$formName]);
HelperFormElement::explodeParameterInArrayElements($feSpecTemplateGroup);
$feSpecNative = $this->expandTemplateGroupFormElement($feSpecTemplateGroup, $feSpecNative);
return $feSpecNative;
}
/**
* Checks if there are templateGroups defined. If yes, expand them. Return expanded feSpecNative array.
*
......@@ -58,20 +85,20 @@ class FillStoreForm {
private function expandTemplateGroupFormElement(array $feSpecTemplateGroup, array $feSpecNative) {
$expanded = array();
if(count($feSpecTemplateGroup)==0) {
if (count($feSpecTemplateGroup) == 0) {
return $feSpecNative; // No templateGroups >> nothing to do >> just return
}
// Iterate over all 'FormElements': part of a templateGroup?
foreach($feSpecNative as $fe) {
$flagCopied=false;
foreach ($feSpecNative as $fe) {
$flagCopied = false;
if($fe[FE_ID_CONTAINER]>0) {
if ($fe[FE_ID_CONTAINER] > 0) {
// Search for a corresponding template group.
foreach ($feSpecTemplateGroup as $templateGroup) {
if ($fe[FE_ID_CONTAINER] = $templateGroup[FE_ID]) {
$flagCopied=true;
$flagCopied = true;
// Get max copies per template group
$maxCopies = ($templateGroup[FE_MAX_LENGTH] == 0 || $templateGroup[FE_MAX_LENGTH] == '') ? FE_TEMPLATE_GROUP_DEFAULT_MAX_LENGTH : $templateGroup[FE_MAX_LENGTH];
......@@ -86,7 +113,7 @@ class FillStoreForm {
}
}
if(!$flagCopied) {
if (!$flagCopied) {
$expanded[] = $fe;
}
}
......@@ -94,33 +121,6 @@ class FillStoreForm {
return $expanded;
}
/**
* Loads a minimal definition of FormElement of the form specified in SIP.
*
* @return array
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function loadFormElementsBasedOnSIP() {
$formName = $this->store->getVar(SIP_FORM, STORE_SIP);
// Preparation for Log, Debug
$this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM);
$feSpecNative = $this->db->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_EXPECT_GE_1, [$formName],
'Form or FormElements not found: ' . ERROR_FORM_NOT_FOUND);
HelperFormElement::explodeParameterInArrayElements($feSpecNative);
$feSpecTemplateGroup = $this->db->sql(SQL_FORM_ELEMENT_CONTAINER_TEMPLATE_GROUP, ROW_REGULAR, [$formName]);
HelperFormElement::explodeParameterInArrayElements($feSpecTemplateGroup);
$feSpecNative = $this->expandTemplateGroupFormElement($feSpecTemplateGroup, $feSpecNative);
return $feSpecNative;
}
/**
* Copies all current form parameter from STORE_CLIENT to STORE_FORM. Checks the values against FormElement
* definition and throws an exception if check fails. FormElements.type=hidden will be taken from STORE_SIP.
......@@ -137,6 +137,11 @@ class FillStoreForm {
$clientValues = $this->store->getStore(STORE_CLIENT);
// If called through 'api/...': get STORE_TYPO3 via SIP parameter.
if (isset($clientValues[CLIENT_TYPO3VARS])) {
$this->store->fillTypo3StoreFromSip($clientValues[CLIENT_TYPO3VARS]);
}
// Retrieve SIP vars, e.g. for HIDDEN elements.
$sipValues = $this->store->getStore(STORE_SIP);
......@@ -161,7 +166,7 @@ class FillStoreForm {
// no: regular situation, take real 'recordid'
$fakeRecordId = isset($sipValues[SIP_MAKE_URLPARAM_UNIQ]) ? 0 : $sipValues[SIP_RECORD_ID];
// Iterate over all formelements. Sanatize values. Built an assoc array $newValues.
// Iterate over all FormElements. Sanatize values. Built an assoc array $newValues.
foreach ($this->feSpecNative AS $formElement) {
// Never get a predefined 'id'
......@@ -228,7 +233,7 @@ class FillStoreForm {
}
}
$this->store->setVarArray($newValues, STORE_FORM, true);
$this->store->setStore($newValues, STORE_FORM, true);
}
/**
......
......@@ -81,6 +81,9 @@ class Store {
/**
* @param string $bodytext
* @param string $fileConfigIni
* @throws UserFormException
* @throws \qfq\CodeException
*/
private function __construct($bodytext = '', $fileConfigIni = '') {
......@@ -100,6 +103,7 @@ class Store {
// TYPO3_FE_USER_GROUP => SANITIZE_ALLOW_ALNUMX,
CLIENT_SIP => SANITIZE_ALLOW_ALNUMX,
CLIENT_TYPO3VARS => SANITIZE_ALLOW_ALNUMX,
CLIENT_RECORD_ID => SANITIZE_ALLOW_DIGIT,
CLIENT_KEY_SEM_ID => SANITIZE_ALLOW_DIGIT,
CLIENT_KEY_SEM_ID_USER => SANITIZE_ALLOW_DIGIT,
......@@ -167,7 +171,6 @@ class Store {
self::fillStoreClient();
self::fillStoreSip();
self::fillStoreExtra();
}
/**
......@@ -212,7 +215,7 @@ class Store {
self::checkMandatoryParameter($config);
self::setVarArray($config, STORE_SYSTEM, true);
self::setStore($config, STORE_SYSTEM, true);
}
/**
......@@ -333,7 +336,7 @@ class Store {
* @throws UserFormException
* @throws \qfq\CodeException
*/
public static function setVarArray(array $dataArray, $store, $flagOverwrite = false) {
public static function setStore(array $dataArray, $store, $flagOverwrite = false) {
// Check valid Storename
if (!isset(self::$sanitizeStore))
......@@ -394,15 +397,15 @@ class Store {
} else {
// NO T3 environment (called by API): restore from SESSION
foreach([ SESSION_FE_USER, SESSION_FE_USER_UID, SESSION_FE_USER_GROUP ] as $key) {
// No T3 environment (called by API): restore from SESSION
foreach ([SESSION_FE_USER, SESSION_FE_USER_UID, SESSION_FE_USER_GROUP] as $key) {
if (isset($_SESSION[SESSION_NAME][$key])) {
$arr[$key] = $_SESSION[SESSION_NAME][$key];
}
}
}
self::setVarArray($arr, STORE_TYPO3, true);
self::setStore($arr, STORE_TYPO3, true);
}
/**
......@@ -425,7 +428,7 @@ class Store {
$arr = \qfq\Sanitize::normalize($arr);
self::setVarArray($arr, STORE_CLIENT, true);
self::setStore($arr, STORE_CLIENT, true);
}
......@@ -447,7 +450,7 @@ class Store {
$param[SIP_URLPARAM] = self::$sip->getQueryStringFromSip($s);
// self::setVarArray(KeyValueStringParser::parse($param, "=", "&"), STORE_SIP);
self::setVarArray($param, STORE_SIP, true);
self::setStore($param, STORE_SIP, true);
}
}
......@@ -530,9 +533,9 @@ class Store {
}
if ($value === false) {
self::setVarArray(array(), STORE_EXTRA, true);
self::setStore(array(), STORE_EXTRA, true);
} else {
self::setVarArray($_SESSION[SESSION_NAME][STORE_EXTRA], STORE_EXTRA, true);
self::setStore($_SESSION[SESSION_NAME][STORE_EXTRA], STORE_EXTRA, true);
}
}
......@@ -679,7 +682,7 @@ class Store {
// Store in SIP Store (cause it's empty until now).
$tmpParam[SIP_SIP] = $sip;
self::setVarArray($tmpParam, STORE_SIP, true);
self::setStore($tmpParam, STORE_SIP, true);
}
......@@ -713,6 +716,69 @@ class Store {
return $tmpParam;
}
/**
* Returns a pointer to this class.
*
* @return null|Sip
*/
public static function getSipInstance() {
return self::$sip;
}
/**
* Fills STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES
*
* @param $tableName
* @throws CodeException
*/
public static function fillStoreTableDefaultColumnType($tableName) {
$db = new qfq\Database();
$tableDefinition = $db->getTableDefinition($tableName);
self::setStore(array_column($tableDefinition, 'Default', 'Field'), STORE_TABLE_DEFAULT, true);
self::setStore(array_column($tableDefinition, 'Type', 'Field'), STORE_TABLE_COLUMN_TYPES, true);
}
/**
* @throws CodeException
* @throws UserFormException
*/
public static function copyT3VarsToSip() {
$tempArray = self::getStore(STORE_TYPO3);
foreach ([TYPO3_FE_USER, TYPO3_FE_USER_UID, TYPO3_FE_USER_GROUP, TYPO3_TT_CONTENT_UID, TYPO3_PAGE_ID, TYPO3_PAGE_TYPE, TYPO3_PAGE_LANGUAGE, TYPO3_BE_USER_LOGGED_IN] as $key) {
if (isset($tempArray[$key])) {
$t3varsArray[$key] = $tempArray[$key];
}
}
$t3varsArray[TYPO3_BE_USER_LOGGED_IN] = (isset($GLOBALS["TSFE"]->beUserLogin) && $GLOBALS["TSFE"]->beUserLogin === true) ? 'yes' : 'no';
$t3varsString = KeyValueStringParser::unparse($t3varsArray, '=', '&');
$t3sip = self::$sip->queryStringToSip($t3varsString, RETURN_SIP);
return $t3sip;
}
/**