Commit 97fc6c0d authored by Carsten  Rose's avatar Carsten Rose
Browse files

Implements #8043 / Escape Class "Exception"

parent b59c4bc6
Pipeline #1756 failed with stage
in 1 minute and 59 seconds
......@@ -63,6 +63,10 @@ class QfqController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
$html = "Generic Exception: " . $e->getMessage();
}
if (isset($e) && $e->getCode() == ERROR_QUIT_QFQ_REGULAR) {
$flagOk = true;
}
if (!$flagOk) {
$html = "<div class='alert alert-warning'>$html</div>";
}
......
......@@ -1290,6 +1290,8 @@ The following `escape`, `hashing`, `action` types are available:
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| S | Stop replace. If the replaced value contains variables, they won't be replaced. |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
| X | Throw exception if variable is not found in the given store(s). Outputs `variable-type-message-violate`_ |
+-------+----------------------------------------------------------------------------------------------------------------------------------+
* The `escape` type is defined by the fourth parameter of the variable. E.g.: `{{name:FE:alnumx:m}}` (m = mysql).
......
......@@ -145,7 +145,7 @@ const ERROR_MESSAGE_HTTP_STATUS = 'httpStatus'; // HTTP Status Code to report
// QFQ Error Codes
const ERROR_UNKNOW_SANITIZE_CLASS = 1001;
const ERROR_QUIT_QFQ_REGULAR = 1001;
const ERROR_CODE_SHOULD_NOT_HAPPEN = 1003;
const ERROR_SIP_MALFORMED = 1005;
const ERROR_SIP_INVALID = 1006;
......@@ -745,6 +745,13 @@ const TOKEN_FOUND_IN_STORE_QUERY = 'query';
const TOKEN_FOUND_AS_COLUMN = 'column';
const TOKEN_FOUND_AS_DEFAULT = 'default';
const VAR_INDEX_VALUE = 0;
const VAR_INDEX_STORE = 1;
const VAR_INDEX_SANATIZE = 2;
const VAR_INDEX_ESCAPE = 3;
const VAR_INDEX_DEFAULT = 4;
const VAR_INDEX_MESSAGE = 5;
const RANDOM_LENGTH = 32;
// FORM - copy from table 'form' of processed form
......
......@@ -329,7 +329,7 @@ class Evaluate {
$arrToken = explode(' ', $token);
// Variable Type 'SQL Statement'
if (in_array(strtoupper($arrToken[0] . ' '), $this->sqlKeywords)) {
if (in_array(strtoupper($arrToken[VAR_INDEX_VALUE] . ' '), $this->sqlKeywords)) {
$foundInStore = TOKEN_FOUND_IN_STORE_QUERY;
return $this->dbArray[$dbIndex]->sql($token, $sqlMode);
......@@ -356,11 +356,11 @@ class Evaluate {
// explode for: <key>:<store priority>:<sanitize class>:<escape>:<default>:<type violate message>
$arrToken = array_merge(KeyValueStringParser::explodeEscape(':', $token, 6), [null, null, null, null, null, null]);
$escapeTypes = (empty($arrToken[3])) ? $this->escapeTypeDefault : $arrToken[3];
$typeMessageViolate = ($arrToken[5] === null || $arrToken[5] === '') ? SANITIZE_TYPE_MESSAGE_VIOLATE_CLASS : $arrToken[5];
$escapeTypes = (empty($arrToken[VAR_INDEX_ESCAPE])) ? $this->escapeTypeDefault : $arrToken[VAR_INDEX_ESCAPE];
$typeMessageViolate = ($arrToken[VAR_INDEX_MESSAGE] === null || $arrToken[VAR_INDEX_MESSAGE] === '') ? SANITIZE_TYPE_MESSAGE_VIOLATE_CLASS : $arrToken[VAR_INDEX_MESSAGE];
// search for value in stores
$value = $this->store->getVar($arrToken[0], $arrToken[1], $arrToken[2], $foundInStore, $typeMessageViolate);
$value = $this->store->getVar($arrToken[VAR_INDEX_VALUE], $arrToken[VAR_INDEX_STORE], $arrToken[VAR_INDEX_SANATIZE], $foundInStore, $typeMessageViolate);
// escape ticks
if (is_string($value)) {
......@@ -398,19 +398,24 @@ class Evaluate {
$value = Support::encryptDoubleCurlyBraces($value);
break;
case TOKEN_ESCAPE_EXCEPTION:
$flagThrowExceptionIfNotFound = true;
// empty values will be handled later.
break;
default:
throw new UserFormException("Unknown escape qualifier: $escape", UNKNOWN_TYPE);
throw new UserFormException("Unknown escape qualifier: $escape", ERROR_UNKNOW_SANITIZE_CLASS);
break;
}
}
} else {
// In case the value is not found and the escape class forces a full stop
if (strpos($escapeTypes, TOKEN_ESCAPE_EXCEPTION) !== false) {
throw new UserFormException($arrToken[VAR_INDEX_MESSAGE] ?? '', ERROR_QUIT_QFQ_REGULAR);
}
}
// Not found and a default is given: take the default.
if ($foundInStore == '' && !empty($arrToken[4])) {
if ($foundInStore == '' && !empty($arrToken[VAR_INDEX_DEFAULT])) {
$foundInStore = TOKEN_FOUND_AS_DEFAULT;
$value = str_replace('\\:', ':', $arrToken[4]);
$value = str_replace('\\:', ':', $arrToken[VAR_INDEX_DEFAULT]);
}
return $value;
......
......@@ -573,6 +573,24 @@ class EvaluateTest extends AbstractDatabaseTest {
// Stop Recursive replace
$this->assertEquals('go start {{hidden:F:alnumx}} end stop', $eval->parse('go {{a:F:all:S}} stop'));
// Check that there is no exception if not found in the first/second store but in third store
$this->assertEquals('go !!digit!! stop', $eval->parse('go {{a:SYF::X}} stop'));
}
/**
* @expectedException \qfq\UserFormException
*
* @throws CodeException
* @throws DbException
* @throws UserFormException
* @throws UserReportException
*/
public function testVariableNotFoundException() {
$eval = new Evaluate($this->store, $this->dbArray[DB_INDEX_DEFAULT]);
$eval->parse('go {{unknownVar:S::X}} stop');
}
/**
......
......@@ -15,6 +15,12 @@ require_once(__DIR__ . '/database/AbstractDatabaseTest.php');
*/
class SaveTest extends AbstractDatabaseTest {
/**
* @throws CodeException
* @throws DbException
* @throws UserFormException
* @throws UserReportException
*/
public function testUpdateRecord() {
$save = new Save([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), array());
......@@ -33,6 +39,12 @@ class SaveTest extends AbstractDatabaseTest {
}
/**
* @throws CodeException
* @throws DbException
* @throws UserFormException
* @throws UserReportException
*/
public function testInsertRecord() {
$save = new Save([F_DB_INDEX => DB_INDEX_DEFAULT], array(), array(), array());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment