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

Implements #11269. REST Post might return a customized answer.

parent 18321a1d
Pipeline #3964 passed with stages
in 5 minutes and 54 seconds
...@@ -70,6 +70,8 @@ All data will imported / exported in JSON notation. ...@@ -70,6 +70,8 @@ All data will imported / exported in JSON notation.
Any QFQ form becomes a REST form via: ``Form > Access > Permit REST: get / insert / update / delete`` Any QFQ form becomes a REST form via: ``Form > Access > Permit REST: get / insert / update / delete``
If the REST endpoint specifies an unknown form or access is forbidden, an HTTP error is reported.
Endpoint Endpoint
-------- --------
...@@ -86,8 +88,8 @@ E.g.: ...@@ -86,8 +88,8 @@ E.g.:
1. List of all persons: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person`` 1. List of all persons: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person``
2. Data of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123`` 2. Data of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123``
3. Adresses of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address`` 3. Addresses of person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address``
4. Adress details of address 45 from person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address/45`` 4. Address details of address 45 from person 123: ``<domain>/typo3conf/ext/qfq/Classes/Api/rest.php/person/123/address/45``
QFQ 'Forms' are used as a 'container' (to define all details). QFQ 'Forms' are used as a 'container' (to define all details).
...@@ -115,11 +117,11 @@ GET - Read ...@@ -115,11 +117,11 @@ GET - Read
A REST (GET) form has two modes: A REST (GET) form has two modes:
data data
Specific content to a given id. Defined via 'form.parameter.restSqlData'. This mode is selected if there is an Specific content to a given id. Defined via ``form.parameter.restSqlData``. This mode is selected if there is an
id>0 given. id>0 given.
list list
A list of records will be exported. Defined via 'form.parameter.restSqlList'. This mode is selected if there is no A list of records will be exported. Defined via ``form.parameter.restSqlList``. This mode is selected if there is no
id or id=0. id or id=0.
.. note:: .. note::
...@@ -199,12 +201,14 @@ POST - Insert ...@@ -199,12 +201,14 @@ POST - Insert
+-------------------+----------------------------------------------------------------------------------+ +-------------------+----------------------------------------------------------------------------------+
| restToken | Optional. User defined string or dynamic token (see :ref:`restAuthorization`). | | restToken | Optional. User defined string or dynamic token (see :ref:`restAuthorization`). |
+-------------------+----------------------------------------------------------------------------------+ +-------------------+----------------------------------------------------------------------------------+
| restSqlPostPut | Optional. Instead of returning the last_insert_id, a customized result might be |
| | specified. E.g. ``{{! SELECT id, token FROM Token WHERE id={{id:R0}} }}`` |
+-------------------+----------------------------------------------------------------------------------+
FormElement: FormElement:
* For each column to save one FormElement with ``FE.name=<column>`` is necessary. * For each column to save one FormElement with ``FE.name=<column>`` is necessary.
* A regular QFQ form can be used as REST Post endpoint * A regular QFQ form can be used as REST Post endpoint.
PUT - Update PUT - Update
------------ ------------
......
...@@ -1068,6 +1068,7 @@ const F_MULTI_MSG_NO_RECORD_TEXT = 'No data'; ...@@ -1068,6 +1068,7 @@ const F_MULTI_MSG_NO_RECORD_TEXT = 'No data';
const F_REST_SQL_LIST = 'restSqlList'; const F_REST_SQL_LIST = 'restSqlList';
const F_REST_SQL_DATA = 'restSqlData'; const F_REST_SQL_DATA = 'restSqlData';
const F_REST_SQL_POST_PUT = 'restSqlPostPut';
const F_REST_PARAM = 'restParam'; const F_REST_PARAM = 'restParam';
const F_REST_TOKEN = 'restToken'; const F_REST_TOKEN = 'restToken';
const CLIENT_REST_ID = '_id'; const CLIENT_REST_ID = '_id';
......
...@@ -209,7 +209,7 @@ class OnString { ...@@ -209,7 +209,7 @@ class OnString {
/** /**
* Split a $_SERVER['PATH_INFO'] of the form '/form1/id1/form2/id2/form3/id3/.../formN[/idN])' to * Split a $_SERVER['PATH_INFO'] of the form '/form1/id1/form2/id2/form3/id3/.../formN[/idN])' to
* $rcArrrIds=[ id1, id2, ..., idN] * $rcArrIds=[ id1, id2, ..., idN]
* return: 'formN' * return: 'formN'
* *
* @param $pathInfo * @param $pathInfo
......
...@@ -564,7 +564,7 @@ class QuickFormQuery { ...@@ -564,7 +564,7 @@ class QuickFormQuery {
$this->pasteClipboard($this->formSpec[F_ID], $formAction); $this->pasteClipboard($this->formSpec[F_ID], $formAction);
if ($formMode == FORM_REST) { if ($formMode == FORM_REST) {
$data = ['id' => $rc]; $data = $this->doRestPostPut($rc);
$flagApiStructureReGroup = false; $flagApiStructureReGroup = false;
break; break;
} }
...@@ -641,7 +641,24 @@ class QuickFormQuery { ...@@ -641,7 +641,24 @@ class QuickFormQuery {
} }
return $this->evaluate->parse($this->formSpec[$key]); return $this->evaluate->parse($this->formSpec[$key]);
}
/**
* @return bool|array
* @throws \CodeException
* @throws \DbException
* @throws \UserFormException
* @throws \UserReportException
*/
private function doRestPostPut($id) {
if (!isset($this->formSpec[F_REST_SQL_POST_PUT])) {
return ['id' => $id];
}
$this->nameGenericRestParam();
return $this->evaluate->parse($this->formSpec[F_REST_SQL_POST_PUT]);
} }
/** /**
...@@ -720,7 +737,7 @@ class QuickFormQuery { ...@@ -720,7 +737,7 @@ class QuickFormQuery {
$feFilter = OnArray::filter($this->feSpecNative, FE_TYPE, FE_TYPE_PILL); $feFilter = OnArray::filter($this->feSpecNative, FE_TYPE, FE_TYPE_PILL);
if (!empty($feFilter)) { if (!empty($feFilter)) {
foreach ($feFilter AS $feParent) { foreach ($feFilter as $feParent) {
if ($feParent[FE_MODE_SQL]) { if ($feParent[FE_MODE_SQL]) {
$mode = $this->evaluate->parse($feParent[FE_MODE_SQL]); $mode = $this->evaluate->parse($feParent[FE_MODE_SQL]);
...@@ -731,7 +748,7 @@ class QuickFormQuery { ...@@ -731,7 +748,7 @@ class QuickFormQuery {
if ($feParent[FE_MODE] == FE_MODE_HIDDEN) { if ($feParent[FE_MODE] == FE_MODE_HIDDEN) {
$feChild = OnArray::filter($this->feSpecNative, FE_ID_CONTAINER, $feParent[FE_ID]); $feChild = OnArray::filter($this->feSpecNative, FE_ID_CONTAINER, $feParent[FE_ID]);
foreach ($feChild AS $fe) { foreach ($feChild as $fe) {
# Search for origin # Search for origin
foreach ($this->feSpecNative as $key => $value) { foreach ($this->feSpecNative as $key => $value) {
...@@ -863,7 +880,7 @@ class QuickFormQuery { ...@@ -863,7 +880,7 @@ class QuickFormQuery {
$arrClipboard = $this->dbArray[$this->dbIndexQfq]->sql($sql); $arrClipboard = $this->dbArray[$this->dbIndexQfq]->sql($sql);
// Process clipboard records. // Process clipboard records.
foreach ($arrClipboard AS $srcIdRecord) { foreach ($arrClipboard as $srcIdRecord) {
$formAction->doAllFormElementPaste($this->feSpecAction, $this->formSpec[F_TABLE_NAME], $this->formSpec[F_TABLE_NAME], "", $srcIdRecord); $formAction->doAllFormElementPaste($this->feSpecAction, $this->formSpec[F_TABLE_NAME], $this->formSpec[F_TABLE_NAME], "", $srcIdRecord);
} }
...@@ -1009,7 +1026,7 @@ class QuickFormQuery { ...@@ -1009,7 +1026,7 @@ class QuickFormQuery {
unset($form[F_PARAMETER]); unset($form[F_PARAMETER]);
// Save specific elements to be expanded later. // Save specific elements to be expanded later.
$parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, FE_FILL_STORE_VAR, F_REST_SQL_LIST, F_REST_SQL_DATA, F_MULTI_SQL]); $parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, FE_FILL_STORE_VAR, F_REST_SQL_LIST, F_REST_SQL_DATA, F_REST_SQL_POST_PUT, F_MULTI_SQL]);
$form[FE_FILL_STORE_VAR] = ''; $form[FE_FILL_STORE_VAR] = '';
$form[F_FORWARD_PAGE] = ''; $form[F_FORWARD_PAGE] = '';
$form[F_REST_SQL_LIST] = ''; $form[F_REST_SQL_LIST] = '';
...@@ -1513,7 +1530,7 @@ class QuickFormQuery { ...@@ -1513,7 +1530,7 @@ class QuickFormQuery {
$method = $this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT); $method = $this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT);
if (false === Support::findInSet(strtolower($method), $this->formSpec[F_REST_METHOD])) { if (false === Support::findInSet(strtolower($method), $this->formSpec[F_REST_METHOD])) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Invalid HTTP method', throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Invalid HTTP method: endpoint (form) not found or access not allowed',
ERROR_MESSAGE_TO_DEVELOPER => "Endpoint '" . $this->formSpec[F_NAME] . "' is not allowed with HTTP method '$method'", ERROR_MESSAGE_TO_DEVELOPER => "Endpoint '" . $this->formSpec[F_NAME] . "' is not allowed with HTTP method '$method'",
ERROR_MESSAGE_HTTP_STATUS => HTTP_401_UNAUTHORIZED ERROR_MESSAGE_HTTP_STATUS => HTTP_401_UNAUTHORIZED
]), ERROR_FORM_REST); ]), ERROR_FORM_REST);
...@@ -1582,7 +1599,7 @@ class QuickFormQuery { ...@@ -1582,7 +1599,7 @@ class QuickFormQuery {
$requiredParameterArr = explode('#', $requiredParameter, 2); $requiredParameterArr = explode('#', $requiredParameter, 2);
$param = explode(',', $requiredParameterArr[0]); $param = explode(',', $requiredParameterArr[0]);
foreach ($param AS $name) { foreach ($param as $name) {
$name = trim($name); $name = trim($name);
......
Supports Markdown
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