diff --git a/CHANGELOG.md b/CHANGELOG.md index 69bee416733fb2a5d668b1a0b749d91c5ebfe3ea..7f6c59c50137d82263e90c166e7cadf237b2e530 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1203,7 +1203,7 @@ Bug Fixes * Dynamic Update has been broken since implementing of 'element-update' (#3180). Now both methods, 'element-update' and 'form-update' should be fine. * qfq-bs.css.less: Fixed problem with 'typeahead input elements' not expanded to Bootstrap column width. Changed - Layout/Design Typeahead drop-down box. Add hoover for the drop-down box with a blue background + Layout/Design Typeahead drop-down box. Add hover for the drop-down box with a blue background * AbstractBuildForm.php: #3374 - textarea elements now contains 'maxlength' attribute. * BuildFormBootstrap.php: wrapping of optional 'submitButtonText' now done with the 'per form' values. * typeahead.php: if there is an exception, the message body is sent as regular 'content' for the drop-down box. At the diff --git a/doc/DRAGANDDROP.md b/doc/DRAGANDDROP.md new file mode 100644 index 0000000000000000000000000000000000000000..14d9b9cd5216ac4d23fdc6d8b618fc8810067b7b --- /dev/null +++ b/doc/DRAGANDDROP.md @@ -0,0 +1,22 @@ +# Drag And Drop + +## Sort +Initialize a dnd container by adding the class "qfq-dnd" + +Set container object class to `class="qfq-dnd qfq-dnd-sort"`. + +Add the data elements: `data-dnd-api="url"` and `data-dnd-key="key"`. + +For the children inside of the container (just the first children): +add `data-dnd-id` to a reference you can handle (probably record id). + +Request will be sent containing following GET variables: + +* dragId = `data-dnd-id` of the dragged object, +* dragPosition = client internal old position of the dragged object. +* setTo = "after" or "before", +* hoverId = `data-dnd-id` id of the element the dragged element is now hovering, meaning before or after. +* hoverPosition = client internal position of currently hovered element. + + +Example: http://something/bla?dragId=uno&dragPosition=1&setTo=before&hoverId=tre&hoverPosition=3 \ No newline at end of file diff --git a/doc/PROTOCOL.md b/doc/PROTOCOL.md index 6f7b93bc536bf8b7976f3e6d711549d3c100ca06..40565f2079627978752e0c71af46dea30a6285fe 100644 --- a/doc/PROTOCOL.md +++ b/doc/PROTOCOL.md @@ -73,11 +73,11 @@ the Client by adding following name/value pairs to the response JSON Stream { - "status": "error", - ... - "field-name": "<field name>", - "field-message": "<message>", - ... + "status": "error", + ... + "field-name": "<field name>", + "field-message": "<message>", + ... } Only one validation failure per request can be reported to Client. @@ -465,7 +465,7 @@ Request Method : GET URL Parameters -: `s=<SIP>` (form, r) +: `s=<SIP>` (form, r) : `action=lock`, `action=extend`, `action=release>` : `recordHashMd5=<value of hidden form element 'recordHashMd5'>` @@ -489,24 +489,28 @@ On `"conflict"` the Client opens the alert as modal dialog (user can't change an form' button. On `"conflict_allow_force"` the Client opens the alert non-modal (default). -## Drag And Drop -Initialize a dnd container by adding the class "qfq-dnd" -### Sorting -Set container object class to "qfq-dnd qfq-dnd-sort". -Add the data elements: data-dnd-api="url" and data-dnd-key="key" -For the childrens inside of the container (just the first children): -add data-dnd-id to a reference you can handle (probably SQL id) +### Drag And Drop (sort) -Request will be sent containing following information: -{"id":2,"value":50,"position":5,"setTo":"after","otherId":4} +Request +: api/dragAndDrop.php -dragId = id of the dragged object -dragPosition = counted original position of the dragged object -setTo = "after" or "before" -hoverId = id of the element the dragged element is now hovering, meaning before or after. -hoverPosition = Position of currently hovered element. +Request Method +: GET + +URL Parameters: + +: `s=<SIP>` (`form=<formname>`) +: +: `dragId=<data-dnd-id of dragged element>` +: `dragPosition=<client internal position (numbering) of element before dragging>` +: `setTo=before`, `setTo=after` +: `hoverId=<data-dnd-id of dragged element>` +: `hoverPosition=<client internal position (numbering) of element after dragging>` +Server Response +: The response contains at least a [Minimal Response]. In addition, a + [HTML Element Response] (need to be defined) may be included. ## Glossary diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index 353e8e9ea3f7bccee6bcf629c9283d38a50bfd5d..1d2209d9a555ef7d4ccb3df03c1e300af63e5c16 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -6218,8 +6218,95 @@ E.g.:: 10.sql = SELECT "p:home&r=0|t:Home|c:qfq-100 qfq-left" AS _pagev -Examples --------- + +Drag and drop +------------- + +Sort/order elements +^^^^^^^^^^^^^^^^^^^ + +Manually sorting and ordering of elements via `HTML5 drag and drop` is supported via QFQ. Any sortable element +should be represented by a database record with an order column. If the elements are unordered, they will be ordered after +the first manual move of an element. + +Functionality is divided into: + +* Display list: the records will be displayed via QFQ/report. +* Update database: updates of the order column are managed by a specific 'drag and drop' definition Form. + +Part 1: Display list +'''''''''''''''''''' + +Display the list of elements via a regular QFQ content record. All 'drag and drop' elements have to be nested by an HTML +element: + +* With `class="qfq-dnd-sort"`. +* With an automatically SIP protected form name: `{{'form=<form name>' AS _data-dnd-api}}` +* Only direct children of such element can be dragged. +* Every children needs a unique identifier `data-dnd-id="<unique>"`. Typically this is the corresponding record id. +* The record needs a dedicated order column, which will be updated through API calls in time. + +The final HTML output: :: + + <div class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234"> + <div class="anyClass" id="<uniq1>" data-dnd-id="55"> + Numbero Uno + </div> + <div class="anyClass" id="<uniq2>" data-dnd-id="18"> + Numbero Deux + </div> + <div class="anyClass" id="<uniq3>" data-dnd-id="27"> + Numbero Tre + </div> + </div> + + +A typical QFQ report which generates those HTML: :: + + 10 { + sql = SELECT '<div id="anytag-', n.id,'" data-dnd-id="', n.id,'">' , n.note, '</div>' + FROM Note AS n + ORDER BY n.ord + + head = <div class="qfq-dnd-sort" {{'form=dndSortNote&grId=28' AS _data-dnd-api}}> + tail = </div> + } + + +Part 2: Update database +''''''''''''''''''''''' + +A dedicated `Form`, without any `FormElements`, is needed to define the database update definition. + +Fields: + +* Name: <custom form name> - used in Part 1 in the `_data-dnd-api` variable. +* Table: <table with the element records> - used to the update the records specified by `dragAndDropOrderSql`. + +* Parameter: + ++-------------------------------------+--------------------------------------------------------------------------------+ +| Attribute | Description | ++=====================================+================================================================================+ +| orderInterval = <number> | Optional. By default '10'. Might be any number > 0. | ++-------------------------------------+--------------------------------------------------------------------------------+ +| orderColumn = <column name> | Optional. By default 'ord'. | ++-------------------------------------+--------------------------------------------------------------------------------+ +| dragAndDropOrderSql = | Query to selects the *same* records as the report in the | +| {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n | same *order!* Inconsistencies results in sort differences. | +| ORDER BY n.ord}} | The columns `id` and `ord` are *mandatory.* | ++-------------------------------------------------------+--------------------------------------------------------------+ + +The form related to the example of part 1: :: + + Form.name: dndSortNote + Form.table: Note + Form.parameter: orderInterval = 1 + Form.parameter: orderColumn = ord + Form.parameter: dragAndDropOrderSql = {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n WHERE n.grId={{grId:S0}} ORDER BY n.ord}} + +Report Examples +--------------- The following section gives some examples of typical reports diff --git a/extension/qfq/api/draganddrop.php b/extension/qfq/api/dragAndDrop.php similarity index 81% rename from extension/qfq/api/draganddrop.php rename to extension/qfq/api/dragAndDrop.php index f5e57c466ef0872c8f9552ea5f6b3295d9811979..f4b8d21895ebd490bda0bf5ef90e26e2d44d7ddb 100644 --- a/extension/qfq/api/draganddrop.php +++ b/extension/qfq/api/dragAndDrop.php @@ -13,6 +13,10 @@ use qfq; require_once(__DIR__ . '/../qfq/store/Store.php'); require_once(__DIR__ . '/../qfq/Constants.php'); require_once(__DIR__ . '/../qfq/QuickFormQuery.php'); +//require_once(__DIR__ . '/../qfq/exceptions/UserFormException.php'); +//require_once(__DIR__ . '/../qfq/exceptions/CodeException.php'); +//require_once(__DIR__ . '/../qfq/exceptions/DbException.php'); +//require_once(__DIR__ . '/../qfq/exceptions/ErrorHandler.php'); /** @@ -55,24 +59,14 @@ try { $data = $qfq->dragAndDrop(); -// $answer[API_REDIRECT] = $qfq->getForwardMode($answer[API_REDIRECT_URL]); $answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS; - $answer[API_MESSAGE] = 'load: success'; - $answer[API_FORM_UPDATE] = $data[API_FORM_UPDATE]; - $answer[API_ELEMENT_UPDATE] = $data[API_ELEMENT_UPDATE]; + $answer[API_MESSAGE] = 'reorder: success'; +// $answer[API_FORM_UPDATE] = $data[API_FORM_UPDATE]; +// $answer[API_ELEMENT_UPDATE] = $data[API_ELEMENT_UPDATE]; // unset($answer[API_FORM_UPDATE][API_ELEMENT_UPDATE]); } catch (qfq\UserFormException $e) { $answer[API_MESSAGE] = $e->formatMessage(); - - $val = Store::getVar(SYSTEM_FORM_ELEMENT, STORE_SYSTEM); - if ($val !== false) - $answer[API_FIELD_NAME] = $val; - - $val = Store::getVar(SYSTEM_FORM_ELEMENT_MESSAGE, STORE_SYSTEM); - if ($val !== false) - $answer[API_FIELD_MESSAGE] = $val; - } catch (qfq\CodeException $e) { $answer[API_MESSAGE] = $e->formatMessage(); } catch (qfq\DbException $e) { diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index 6dc85c838d5026dbce982f9eef30a0b89d0ff66f..bbea73faf0f94c9a4a4918e5dadb2e2ac7adc5e4 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -86,6 +86,8 @@ abstract class AbstractBuildForm { * @param array $feSpecAction * @param array $feSpecNative * @param array $db + * @throws CodeException + * @throws UserFormException */ public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative, array $db = null) { $this->formSpec = $formSpec; @@ -172,6 +174,8 @@ abstract class AbstractBuildForm { * @param array $latestFeSpecNative * @return array|string $mode=LOAD_FORM: The whole form as HTML, $mode=FORM_UPDATE: array of all * formElement.dynamicUpdate-yes values/states + * @throws CodeException + * @throws DbException * @throws UserFormException */ public function process($mode, $htmlElementNameIdZero = false, $latestFeSpecNative = array()) { @@ -247,6 +251,8 @@ abstract class AbstractBuildForm { * * @param string $mode * @return string + * @throws CodeException + * @throws UserFormException */ public function head($mode = FORM_LOAD) { $html = ''; @@ -276,6 +282,8 @@ abstract class AbstractBuildForm { * * @return string String: <a href="?pageId&sip=....">Edit</a> <small>[sip:..., r:..., urlparam:..., * ...]</small> + * @throws CodeException + * @throws UserFormException */ public function createFormEditorUrl($form, $recordId, array $param = array()) { @@ -338,6 +346,8 @@ abstract class AbstractBuildForm { * Build MD5 from the current record. Return HTML Input element. * * @return string + * @throws CodeException + * @throws UserFormException */ public function buildInputRecordHashMd5() { @@ -357,6 +367,9 @@ abstract class AbstractBuildForm { * @param $recordId * * @return string + * @throws CodeException + * @throws DbException + * @throws UserFormException */ public function buildRecordHashMd5($tableName, $recordId) { $record = array(); @@ -372,6 +385,8 @@ abstract class AbstractBuildForm { * Create HTML Input vars to detect bot automatic filling of forms. * * @return string + * @throws CodeException + * @throws UserFormException */ public function getHoneypotVars() { $html = ''; @@ -442,6 +457,9 @@ abstract class AbstractBuildForm { * See: https://www.w3.org/wiki/HTML/Elements/form#HTML_Attributes * * @return string + * @throws CodeException + * @throws DbException + * @throws UserFormException */ public function getEncType() { @@ -457,6 +475,10 @@ abstract class AbstractBuildForm { * @param array|string $value * * @return array|string + * @throws CodeException + * @throws DbException + * @throws UserFormException + * @throws UserReportException */ private function processReportSyntax($value) { @@ -502,6 +524,10 @@ abstract class AbstractBuildForm { * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE * * @return string + * @throws CodeException + * @throws DbException + * @throws UserFormException + * @throws UserReportException */ public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, array &$json, $modeCollectFe = FLAG_DYNAMIC_UPDATE, $htmlElementNameIdZero = false, @@ -672,6 +698,10 @@ abstract class AbstractBuildForm { * @param array $formElement * * @return array + * @throws CodeException + * @throws DbException + * @throws UserFormException + * @throws UserReportException */ private function prepareFillStoreFireLdap(array $formElement) { @@ -767,6 +797,8 @@ abstract class AbstractBuildForm { * save/update. * * @return string + * @throws CodeException + * @throws UserFormException */ private function prepareT3VarsForSave() { @@ -802,6 +834,8 @@ abstract class AbstractBuildForm { * Get all elements from STORE_ADDITIONAL_FORM_ELEMENTS and return them as a string. * * @return string + * @throws CodeException + * @throws UserFormException */ private function buildAdditionalFormElements() { @@ -816,6 +850,8 @@ abstract class AbstractBuildForm { * @param array $json * * @return string <input type='hidden' name='s' value='<sip>'> + * @throws CodeException + * @throws UserFormException */ public function buildHiddenSip(array &$json) { @@ -921,6 +957,7 @@ abstract class AbstractBuildForm { * @param array $feMode * * @return array + * @throws UserFormException */ private function getJsonFeMode($feMode) { @@ -970,6 +1007,7 @@ abstract class AbstractBuildForm { * @param string $addClass * * @return string + * @throws CodeException */ public function buildLabel($htmlFormElementName, $label, $addClass = '') { $attributes = Support::doAttribute('for', $htmlFormElementName); @@ -985,6 +1023,8 @@ abstract class AbstractBuildForm { * * @param $toolTipNew * @return string + * @throws CodeException + * @throws UserFormException */ public function deriveNewRecordUrlFromExistingSip(&$toolTipNew) { @@ -1048,6 +1088,8 @@ abstract class AbstractBuildForm { * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE * * @return string complete rendered HTML input element. + * @throws CodeException + * @throws UserFormException */ public function buildInput(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { $textarea = ''; @@ -1192,6 +1234,7 @@ abstract class AbstractBuildForm { * @param array $formElement * * @return string + * @throws CodeException * @throws UserFormException */ private function typeAheadBuildParam(array &$formElement) { @@ -1297,6 +1340,7 @@ abstract class AbstractBuildForm { * @param bool $flagOmitEmpty * * @return string + * @throws CodeException */ private function getAttributeList(array $formElement, array $attributeList, $flagOmitEmpty = true) { $attribute = ''; @@ -1315,6 +1359,7 @@ abstract class AbstractBuildForm { * * @param bool $cssDisable * @return string + * @throws CodeException * @throws UserFormException */ private function getAttributeFeMode($feMode, $cssDisable = true) { @@ -1371,6 +1416,7 @@ abstract class AbstractBuildForm { * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE* * * @return string + * @throws CodeException * @throws UserFormException */ public function buildCheckbox(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) { @@ -1426,6 +1472,7 @@ abstract class AbstractBuildForm { * @param array $itemKey * @param array $itemValue * + * @throws CodeException * @throws UserFormException */ public function getKeyValueListFromSqlEnumSpec(array $formElement, array &$itemKey, array &$itemValue) { diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php index 0a686799147e0d6012c59bf732b373e44f83aa12..15e25e47e970109b3b404872682973c75f1c0a96 100644 --- a/extension/qfq/qfq/BuildFormBootstrap.php +++ b/extension/qfq/qfq/BuildFormBootstrap.php @@ -383,7 +383,9 @@ class BuildFormBootstrap extends AbstractBuildForm { * @param array $json * @return string * @throws CodeException + * @throws DbException * @throws UserFormException + * @throws UserReportException */ private function buildPillNavigation($mode = FORM_LOAD, array $pillArray, array &$json) { $pillButton = ''; @@ -595,6 +597,7 @@ class BuildFormBootstrap extends AbstractBuildForm { fileDeleteUrl: '$apiDir/file.php?$actionDelete' }); + var qfqRecordList = new QfqNS.QfqRecordList('$apiDeletePhp'); }) </script> diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 9a78fe60cd2a0c9514ba7635f0a26f355e49ca07..969a84179d703c67433e90a8f88806506739cded 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -248,6 +248,7 @@ const ERROR_DOWNLOAD_NO_FILES = 1701; const ERROR_DOWNLOAD_NOTHING_TO_DO = 1702; const ERROR_DOWNLOAD_UNEXPECTED_MIME_TYPE = 1703; const ERROR_DOWNLOAD_UNEXPECTED_NUMBER_OF_SOURCES = 1704; +const ERROR_DOWNLOAD_FILE_NOT_READABLE = 1705; // KeyValueParser const ERROR_KVP_VALUE_HAS_NO_KEY = 1900; @@ -547,6 +548,7 @@ const SYSTEM_DOWNLOAD_POPUP = 'hasDownloadPopup'; // Marker which is set to 'tru const DOWNLOAD_POPUP_REQUEST = 'true'; const DOWNLOAD_POPUP_REPLACE_TEXT = '#downloadPopupReplaceText#'; const DOWNLOAD_POPUP_REPLACE_TITLE = '#downloadPopupReplaceTitle#'; +const SYSTEM_DRAG_AND_DROP_JS = 'hasDragAndDropJS'; const SYSTEM_PARAMETER_LANGUAGE_FIELD_NAME = 'parameterLanguageFieldName'; const CSS_REQUIRED = 'required-field'; @@ -648,6 +650,7 @@ const MODE_LDAP_MULTI = 'ldapMulti'; // api/save.php, api/delete.php, api/load.php const API_DELETE_PHP = 'delete.php'; const API_DOWNLOAD_PHP = 'download.php'; +const API_DRAG_AND_DROP_PHP = 'dragAndDrop.php'; const API_STATUS = 'status'; const API_MESSAGE = 'message'; @@ -853,6 +856,9 @@ const F_NEW_BUTTON_GLYPH_ICON = SYSTEM_NEW_BUTTON_GLYPH_ICON; const F_ENTER_AS_SUBMIT = SYSTEM_ENTER_AS_SUBMIT; const F_DRAG_AND_DROP_ORDER_SQL = 'dragAndDropOrderSql'; +const F_ORDER_INTERVAL = 'orderInterval'; +const F_ORDER_COLUMN = 'orderColumn'; +const F_ORDER_COLUMN_NAME = 'ord'; // FORM_ELEMENT_STATI const FE_MODE_SHOW = 'show'; @@ -1423,3 +1429,15 @@ const EXCEPTION_STACKTRACE = 'Stacktrace'; const EXCEPTION_TABLE_CLASS = 'table table-hover qfq-table-80'; +// Drag And Drop +const DND_DRAG_ID = 'dragId'; +const DND_DRAG_POSITION = 'dragPosition'; +const DND_SET_TO = 'setTo'; +const DND_SET_TO_BEFORE = 'before'; +const DND_SET_TO_AFTER = 'after'; +const DND_HOVER_ID = 'hoverId'; +const DND_HOVER_POSITION = 'hoverPosition'; +const DND_COLUMN_ID = 'id'; +const DND_COLUMN_ORD = 'ord'; +const DND_COLUMN_ORD_NEW = 'ordNew'; +const DND_DATA_DND_API = 'data-dnd-api'; \ No newline at end of file diff --git a/extension/qfq/qfq/Evaluate.php b/extension/qfq/qfq/Evaluate.php index b29a27101aadbd1475977026aea2108a6b3cd00c..c84538ac9283f2ad88ad4ef3c9ac6888c4a7d0f5 100644 --- a/extension/qfq/qfq/Evaluate.php +++ b/extension/qfq/qfq/Evaluate.php @@ -197,6 +197,59 @@ class Evaluate { return $result; } + /** + * @param $arrToken + * @param $dbIndex + * @param $foundInStore + * @return string + * @throws CodeException + * @throws UserFormException + * @throws UserReportException + */ + private function inlineLink($arrToken, $dbIndex, &$foundInStore){ + + $token = OnString::trimQuote(trim(implode(' ', $arrToken))); + + if ($this->link === null) { + $this->link = new Link($this->store->getSipInstance(), $dbIndex); + } + + $foundInStore = TOKEN_FOUND_AS_COLUMN; + + return $this->link->renderLink($token); + } + + /** + * @param $arrToken + * @param $dbIndex + * @param $foundInStore + * @return string + * @throws CodeException + * @throws UserFormException + * @throws UserReportException + */ + private function inlineDataDndApi($arrToken, $dbIndex, &$foundInStore){ + + $token = OnString::trimQuote(trim(implode(' ', $arrToken))); + if(empty($token)){ + throw new UserReportException('Missing form name for "data-dnd-api"', ERROR_MISSING_FORM); + } + + if ($this->link === null) { + $this->link = new Link($this->store->getSipInstance(), $dbIndex); + } + + $foundInStore = TOKEN_FOUND_AS_COLUMN; + + $s = $this->link->renderLink('U:' . $token . '|s|r:8'); + + // Flag to add DND JS code later on. + $this->store->setVar(SYSTEM_DRAG_AND_DROP_JS, 'true', STORE_SYSTEM); + + // data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s={{'U:form=<form name>[¶mX=<any value>]|s|r:8' AS _link}}" + return DND_DATA_DND_API . '="' . API_DIR . '/' . API_DRAG_AND_DROP_PHP . '?s=' . $s . '"'; + } + /** * Tries to substitute $token. * Token might be: @@ -244,7 +297,7 @@ class Evaluate { $sqlMode = ROW_REGULAR; } - // Extract token: check if this is a SQL Statement + // Extract token: check if this is a 'variable', 'SQL Statement', 'link', 'data-dnd-api' $arrToken = explode(' ', $token); // Variable Type 'SQL Statement' @@ -254,23 +307,22 @@ class Evaluate { return $this->dbArray[$dbIndex]->sql($token, $sqlMode); } - // Variable Type '... AS LINK' + // Variable Type '... AS _link', '... as data-dnd-api' $countToken = count($arrToken); if ($countToken > 2 && strcasecmp($arrToken[$countToken - 2], 'as') == 0) { $type = OnString::stripFirstCharIf('_', $arrToken[$countToken - 1]); - if (strcasecmp($type, 'link') == 0) { - - $str = OnString::trimQuote(substr($token, 0, strlen($token) - 8)); // strlen('_as_link')=8 + array_pop($arrToken); // remove 'link' | 'data-dnd-api' + array_pop($arrToken); // remove 'as' - if ($this->link === null) { - $this->link = new Link($this->store->getSipInstance(), $dbIndex); - } + if (strcasecmp($type, COLUMN_LINK ) == 0) { + return($this->inlineLink($arrToken, $dbIndex,$foundInStore)); + } - $foundInStore = TOKEN_FOUND_AS_COLUMN; + if($type == DND_DATA_DND_API){ + return($this->inlineDataDndApi($arrToken, $dbIndex,$foundInStore)); - return $this->link->renderLink($str); } } diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php index 87f91c84021fb3fb8d67520d030e2c54cc15de52..49df976d0fd4ce20185a75cdac1e3f14bf04c898 100644 --- a/extension/qfq/qfq/QuickFormQuery.php +++ b/extension/qfq/qfq/QuickFormQuery.php @@ -44,6 +44,7 @@ require_once(__DIR__ . '/BodytextParser.php'); require_once(__DIR__ . '/Delete.php'); require_once(__DIR__ . '/form/FormAction.php'); require_once(__DIR__ . '/form/Dirty.php'); +require_once(__DIR__ . '/form/DragAndDrop.php'); /* * Form will be called @@ -61,8 +62,7 @@ require_once(__DIR__ . '/form/Dirty.php'); * Class Qfq * @package qfq */ -class QuickFormQuery -{ +class QuickFormQuery { /** * @var \qfq\Store instantiated class @@ -127,8 +127,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - public function __construct(array $t3data = array(), $phpUnit = false) - { + public function __construct(array $t3data = array(), $phpUnit = false) { $this->phpUnit = $phpUnit; @@ -197,8 +196,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - public function getForwardMode() - { + public function getForwardMode() { $forwardPage = $this->formSpec[F_FORWARD_PAGE]; @@ -222,11 +220,11 @@ class QuickFormQuery * @return string * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - public function process() - { + public function process() { $html = ''; if ($this->store->getVar(TYPO3_DEBUG_SHOW_BODY_TEXT, STORE_TYPO3) === 'yes') { @@ -242,6 +240,11 @@ class QuickFormQuery $html .= $this->getModalCode(); } + // Only needed if there are 'drag and drop' elements. + if ($this->store->getVar(SYSTEM_DRAG_AND_DROP_JS, STORE_SYSTEM) == 'true') { + $html .= $this->getDragAndDropCode(); + } + $class = $this->store->getVar(SYSTEM_CSS_CLASS_QFQ_CONTAINER, STORE_SYSTEM); if ($class) { $html = Support::wrapTag("<div class='$class'>", $html); @@ -253,8 +256,7 @@ class QuickFormQuery /** * Determine the name of the language parameter field, which has to be taken to fill language specific defintions. */ - private function setParameterLanguageFieldName() - { + private function setParameterLanguageFieldName() { $typo3PageLanguage = $this->store->getVar(TYPO3_PAGE_LANGUAGE, STORE_TYPO3); if (empty($typo3PageLanguage)) { @@ -284,11 +286,11 @@ class QuickFormQuery * @return array|string * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - private function doForm($formMode) - { + private function doForm($formMode) { $data = ''; $foundInStore = ''; @@ -493,8 +495,8 @@ class QuickFormQuery case FORM_DRAG_AND_DROP: $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD); - $draganddrop = new DragAndDrop(); - $draganddrop->process($this->formSpec[F_TABLE_NAME], $this->formSpec[F_DRAG_AND_DROP_ORDER_SQL]); + $dragAndDrop = new DragAndDrop($this->formSpec); + $dragAndDrop->process($this->formSpec); $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_LOAD); break; @@ -533,8 +535,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - private function setForwardModePage() - { + private function setForwardModePage() { if ('url' != substr($this->formSpec[F_FORWARD_MODE], 0, 3)) { return false; @@ -592,8 +593,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - private function pasteClipboard($formId, FormAction $formAction) - { + private function pasteClipboard($formId, FormAction $formAction) { if (!$this->isPasteRecord()) { return; @@ -618,8 +618,7 @@ class QuickFormQuery /** * @return bool true if there is at least one paste record, else false. */ - private function isPasteRecord() - { + private function isPasteRecord() { foreach ($this->feSpecAction as $formElement) { if ($formElement[FE_TYPE] == FE_TYPE_PASTE) { @@ -642,8 +641,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - private function buildNSetReloadUrl(array $formSpec, $recordId) - { + private function buildNSetReloadUrl(array $formSpec, $recordId) { $formSpec[F_FORWARD_MODE] = API_ANSWER_REDIRECT_URL_SKIP_HISTORY; @@ -681,8 +679,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - private function loadFormSpecification($mode, $recordId, &$foundInStore = '') - { + private function loadFormSpecification($mode, $recordId, &$foundInStore = '') { // formName if (false === ($formName = $this->getFormName($mode, $foundInStore))) { @@ -823,8 +820,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - public function getNativeFormElements($sql, array $param, $formSpec) - { + public function getNativeFormElements($sql, array $param, $formSpec) { $feSpecNative = $this->dbArray[$this->dbIndexQfq]->sql($sql, ROW_REGULAR, $param); @@ -864,8 +860,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - private function explodeTemplateGroupElements(array $elements) - { + private function explodeTemplateGroupElements(array $elements) { $new = array(); // No FormElements or no NAME_TG_COPIES column: nothing to do, return. @@ -921,8 +916,7 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - public function getFormName($mode, &$foundInStore = '') - { + public function getFormName($mode, &$foundInStore = '') { $dummy = array(); switch ($mode) { @@ -932,6 +926,7 @@ class QuickFormQuery case FORM_SAVE: case FORM_UPDATE: case FORM_DELETE: + case FORM_DRAG_AND_DROP: $store = STORE_SIP; break; default: @@ -960,8 +955,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - private function modeCleanFormConfig($mode, array $form) - { + private function modeCleanFormConfig($mode, array $form) { switch ($mode) { case FORM_DELETE: @@ -992,8 +986,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - private function syncSystemFormConfig(array $formSpec) - { + private function syncSystemFormConfig(array $formSpec) { $keys = [F_BS_COLUMNS, F_BS_LABEL_COLUMNS, @@ -1063,8 +1056,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - private function initForm(array $formSpec) - { + private function initForm(array $formSpec) { Support::setIfNotSet($formSpec, F_EXTRA_DELETE_FORM, ''); Support::setIfNotSet($formSpec, F_SUBMIT_BUTTON_TEXT, ''); @@ -1105,8 +1097,7 @@ class QuickFormQuery * @throws \qfq\UserFormException * @internal param $foundInStore */ - private function validateForm($formNameFoundInStore, $formMode) - { + private function validateForm($formNameFoundInStore, $formMode) { // Retrieve record_id either from SIP (prefered) or via URL $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore); @@ -1201,8 +1192,7 @@ class QuickFormQuery * @throws DbException * @throws UserFormException */ - private function fillStoreWithRecord($table, $recordId, $store = STORE_RECORD) - { + private function fillStoreWithRecord($table, $recordId, $store = STORE_RECORD) { if ($recordId !== false && $recordId > 0) { $record = $this->dbArray[$this->dbIndexData]->sql("SELECT * FROM $table WHERE id = ?", ROW_EXPECT_1, [$recordId]); $this->store->setStore($record, $store, true); @@ -1217,8 +1207,7 @@ class QuickFormQuery * * @return array to build JSON */ - private function groupElementUpdateEntries(array $dataArray) - { + private function groupElementUpdateEntries(array $dataArray) { $collect = array(); foreach ($dataArray as $data) { @@ -1247,15 +1236,13 @@ class QuickFormQuery * @throws UserFormException * @throws UserReportException */ - private function doReport() - { + private function doReport() { $report = new Report($this->t3data, $this->eval, $this->phpUnit); $html = $report->process($this->t3data['bodytext']); return $html; - } /** @@ -1264,11 +1251,11 @@ class QuickFormQuery * @return string * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - public function saveForm() - { + public function saveForm() { $json = $this->doForm(FORM_SAVE); @@ -1281,11 +1268,11 @@ class QuickFormQuery * @return array * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - public function updateForm() - { + public function updateForm() { $json = $this->doForm(FORM_UPDATE); @@ -1298,11 +1285,11 @@ class QuickFormQuery * @return array * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - public function dragAndDrop() - { + public function dragAndDrop() { $json = $this->doForm(FORM_DRAG_AND_DROP); @@ -1315,11 +1302,11 @@ class QuickFormQuery * @return array * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ - public function delete() - { + public function delete() { return $this->doForm(FORM_DELETE); @@ -1333,8 +1320,7 @@ class QuickFormQuery * @throws CodeException * @throws UserFormException */ - private function newRecordCreateSip(array $sipArray, $recordId) - { + private function newRecordCreateSip(array $sipArray, $recordId) { $tmpParam = array(); @@ -1372,8 +1358,7 @@ class QuickFormQuery /** * @return string */ - private function getModalCode() - { + private function getModalCode() { $code = <<<EOF <!-- Modal --> @@ -1402,5 +1387,21 @@ EOF; return $code; } + /** + * @return string + */ + private function getDragAndDropCode() { + + $code = <<<EOF + <script type = "text/javascript" > + var dragi = new QfqNS . DragAndDrop($('.qfq-dnd-sort')); + dragi . makeSortable(); + </script> +EOF; + + return $code; + + } + } \ No newline at end of file diff --git a/extension/qfq/qfq/form/DragAndDrop.php b/extension/qfq/qfq/form/DragAndDrop.php index 39f18f231896ab8f17cda1a4781f63a333e6cff7..9be716f0fe64059ca7972cbe5a07c17bcf0c2f9a 100644 --- a/extension/qfq/qfq/form/DragAndDrop.php +++ b/extension/qfq/qfq/form/DragAndDrop.php @@ -10,11 +10,13 @@ namespace qfq; //use TYPO3\CMS\Core\FormProtection\Exception; -require_once(__DIR__ . '/../store/Sip.php'); -require_once(__DIR__ . '/../store/Session.php'); +//require_once(__DIR__ . '/../store/Sip.php'); +//require_once(__DIR__ . '/../store/Session.php'); +require_once(__DIR__ . '/../store/Store.php'); require_once(__DIR__ . '/../Constants.php'); -require_once(__DIR__ . '/../helper/Ldap.php'); +//require_once(__DIR__ . '/../helper/Ldap.php'); require_once(__DIR__ . '/../database/Database.php'); +require_once(__DIR__ . '/../Evaluate.php'); /** @@ -29,140 +31,132 @@ class DragAndDrop { private $db = null; /** - * @var array + * @var Store */ - private $vars = array(); + private $store = null; + /** + * @var Evaluate instantiated class + */ + protected $evaluate = null; // copy of the loaded form /** - * @return array|int + * @var array + */ + private $formSpec = null; + + /** + * @param array $formSpec F_TABLE_NAME, F_DRAG_AND_DROP_ORDER_SQL, F_DRAG_AND_DROP_INTERVAL + * @param bool|false $phpUnit + * * @throws CodeException * @throws DbException * @throws UserFormException */ - public function process($tableName, $dragAndDropOrderSql) { - - $arr = array(); - $dbIndex = DB_INDEX_DEFAULT; //TODO hier muss noch die aktuelle DB ermittelt werden (kann im iform angegeben sein) - - $sipClass = new Sip(); + public function __construct(array $formSpec = array(), $phpUnit = false) { - $sipVars = $sipClass->getVarsFromSip($this->vars[TYPEAHEAD_API_SIP]); - - // Check for an optional given dbIndex: '[<int>]SELECT ...' - $sql = $sipVars[FE_TYPEAHEAD_SQL]; - if ($sql[0] === '[') { - $pos = strpos($sql, ']'); - $dbIndex = substr($sql, 1, $pos - 1); - $sipVars[FE_TYPEAHEAD_SQL] = substr($sql, $pos + 1); - } + $this->formSpec = $formSpec; + $dbIndex = DB_INDEX_DEFAULT; //TODO hier muss noch die aktuelle DB ermittelt werden (kann im Form angegeben sein) - Gerade im Formular FORM Editor genau testen! $this->db = new Database($dbIndex); - if (isset($sipVars[FE_TYPEAHEAD_SQL])) { - if($this->vars[TYPEAHEAD_API_PREFETCH] == '') { - $arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]); - } else { - $arr = $this->typeAheadSqlPrefetch($sipVars, $this->vars[TYPEAHEAD_API_PREFETCH]); - } - } elseif (isset($sipVars[FE_LDAP_SERVER])) { - $ldap = new Ldap(); - - if ($this->vars[TYPEAHEAD_API_PREFETCH] == '') { - $mode = MODE_LDAP_MULTI; - $key = $this->vars[TYPEAHEAD_API_QUERY]; - } else { - $mode = MODE_LDAP_PREFETCH; - $key = $this->vars[TYPEAHEAD_API_PREFETCH]; - } - - $arr = $ldap->process($sipVars, $key, $mode); - } - - return $arr; + $this->store = Store::getInstance('', $phpUnit); +// $this->evaluate = new Evaluate($this->store, $this->db); } /** - * Do a wildcard search on the prepared statement $config[FE_TYPEAHEAD_SQL]. - * All '?' will be replaced by '%$value%'. - * If there is no 'LIMIT x' defined, append it. - * Returns an dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ] * - * @param array $config - * @param string $value - * - * @return array + * @return array|int * @throws CodeException * @throws DbException * @throws UserFormException + * @throws UserReportException */ - private function typeAheadSql(array $config, $value) { - $values = array(); - - $sql = $config[FE_TYPEAHEAD_SQL]; - $value = '%' . $value . '%'; - $cnt = substr_count($sql, '?'); + public function process() { - if ($cnt == 0) { - throw new UserFormException("Missing at least one '?' in " . FE_TYPEAHEAD_SQL); - } + $dragId = $this->store->getVar(DND_DRAG_ID, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX); + $setTo = $this->store->getVar(DND_SET_TO, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX); + $hoverId = $this->store->getVar(DND_HOVER_ID, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX); - for ($ii = 0; $ii < $cnt; $ii++) { - $values[] = $value; - } + $orderInterval = empty($this->formSpec[F_ORDER_INTERVAL]) ? 1 : $this->formSpec[F_ORDER_INTERVAL]; + $orderColumn = empty($this->formSpec[F_ORDER_COLUMN]) ? F_ORDER_COLUMN_NAME : $this->formSpec[F_ORDER_COLUMN]; - if (!$this->db->hasLimit($sql)) { - $sql .= ' LIMIT ' . $config[FE_TYPEAHEAD_LIMIT]; + if (!is_array($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL])) { + return []; } - $arr = $this->db->sql($sql, ROW_REGULAR, $values); - if ($arr == false || count($arr) == 0) { - return array(); - } + $this->reorder($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL], $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $this->formSpec[F_TABLE_NAME]); - return $this->db->makeArrayDict($arr, TYPEAHEAD_SQL_KEY_NAME, API_TYPEAHEAD_VALUE, API_TYPEAHEAD_KEY, API_TYPEAHEAD_VALUE); + return []; } /** - * Returns a dict array [ API_TYPEAHEAD_KEY => key, API_TYPEAHEAD_VALUE => value ] with the prefetch result - * - * @param array $config - * @param string $key - * - * @return array + * @param array $rows + * @param $dragId + * @param $setTo + * @param $hoverId + * @param $orderColumn + * @param $orderInterval + * @param $tableName * @throws CodeException * @throws DbException * @throws UserFormException */ + private function reorder(array $rows, $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $tableName) { + $ord = $orderInterval; + $ordDragOld = -1; - private function typeAheadSqlPrefetch(array $config, $key) { - $keys = array(); + // Reorder. Get index for 'drag' and 'hover' + foreach ($rows as $key => $row) { - $sql = $config[FE_TYPEAHEAD_SQL_PREFETCH]; - if ($config[FE_TYPEAHEAD_SQL_PREFETCH] == '') { - throw new UserFormException("Missing definition for `" . FE_TYPEAHEAD_SQL_PREFETCH . "`", ERROR_MISSING_TYPE_AHEAD_SQL_PREFETCH); - } + // the dragged element: skip old position. + if ($row[DND_COLUMN_ID] == $dragId) { + $ordDragOld = $row[DND_COLUMN_ORD]; + continue; + } - $cnt = substr_count($sql, '?'); - if ($cnt == 0) { - throw new UserFormException("Missing at least one '?' in " . FE_TYPEAHEAD_SQL_PREFETCH); + // the dragged element: new position. + if ($row[DND_COLUMN_ID] == $hoverId) { + + switch ($setTo) { + case DND_SET_TO_BEFORE: + $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord); + $ord += $orderInterval; + $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord); + break; + + case DND_SET_TO_AFTER: + $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord); + $ord += $orderInterval; + $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord); + break; + + default: + throw new CodeException('Unkown setTo string', $setTo, ERROR_UNKNOWN_TOKEN); + } + } else { + $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord); + } + $ord += $orderInterval; } + } - for ($ii = 0; $ii < $cnt; $ii++) { - $keys[] = $key; - } + /** + * @param $tableName + * @param $orderColumn + * @param $id + * @param $ordOld + * @param $ordNew + * @throws CodeException + * @throws DbException + * @throws UserFormException + */ + private function setNewOrder($tableName, $orderColumn, $id, $ordOld, $ordNew) { - $arr = $this->db->sql($sql, ROW_REGULAR, $keys); - if ($arr == false || count($arr) == 0) { - return array(); + if ($ordNew == $ordOld) { + return; } - // return first result as key-value pair (concatenate columns) - $value = ''; - foreach($arr[0] AS $name => $column) { - $value .= $column; - } - return [ [ API_TYPEAHEAD_KEY => $key, API_TYPEAHEAD_VALUE => $value ] ]; + $this->db->sql("UPDATE $tableName SET $orderColumn=? WHERE id=?", ROW_REGULAR, [$ordNew, $id]); } - } \ No newline at end of file diff --git a/extension/qfq/qfq/form/FormAction.php b/extension/qfq/qfq/form/FormAction.php index 43edcf6bfb3b36bf92e7cddd736b6c0784d91c0b..dd57b7ffee2e6e8b294d14d476c2e903cfd0add3 100644 --- a/extension/qfq/qfq/form/FormAction.php +++ b/extension/qfq/qfq/form/FormAction.php @@ -28,12 +28,15 @@ class FormAction { * @var Evaluate instantiated class */ protected $evaluate = null; // copy of the loaded form + private $formSpec = array(); private $primaryTableName = ''; + /** * @var Database */ private $db = null; + /** * @var Store */ @@ -71,6 +74,7 @@ class FormAction { * ACTION_ELEMENT_DELETED: if a record has been deleted (only in recursive calls, not the initial one) * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ @@ -245,6 +249,7 @@ class FormAction { * @param array $feSpecAction * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ diff --git a/extension/qfq/qfq/report/Download.php b/extension/qfq/qfq/report/Download.php index 6d63a592887bb689e75ce6e15c84572c97970d67..8a2b0ac9f6ed52ec36be5b0135c7a12b347c8594 100644 --- a/extension/qfq/qfq/report/Download.php +++ b/extension/qfq/qfq/report/Download.php @@ -94,6 +94,16 @@ class Download { */ private function concatPdfFiles(array $files) { + // Remove empty entries. Might happen if there was no upload + $files = OnArray::removeEmptyElementsFromArray($files); + + // Check that all files exist and readable + foreach ($files AS $filename) { + if(!is_readable($filename)){ + throw new downloadException("Error reading file $filename. Not found or no permission", ERROR_DOWNLOAD_FILE_NOT_READABLE); + } + } + switch (count($files)) { case 0: return ''; diff --git a/extension/qfq/qfq/report/Link.php b/extension/qfq/qfq/report/Link.php index 6e3a6990ca9d7585d42d489c230470db91ed4008..578df997a038386fe3652a5899bf6f9685ad17bd 100644 --- a/extension/qfq/qfq/report/Link.php +++ b/extension/qfq/qfq/report/Link.php @@ -262,6 +262,7 @@ class Link { * 4: <a href=url>Text</a> * 5: text * 6: url + * 8: SIP only - 's=badcaffee1234' * * r=render mode, u=url, t:text and/or image. * @@ -308,10 +309,15 @@ class Link { $this->renderControl[7][1][0] = 6; $this->renderControl[7][1][1] = 6; + $this->renderControl[8][0][0] = 0; + $this->renderControl[8][0][1] = 0; + $this->renderControl[8][1][0] = 8; + $this->renderControl[8][1][1] = 8; + } /** - * In render mode 3,4,5 there is no '<a href ...>'. Nevertheless, tooltip and BS Button should be displaye. + * In render mode 3,4,5 there is no '<a href ...>'. Nevertheless, tooltip and BS Button should be displayed. * Do this by applying a '<span>' attribute around the text. * * @param array $vars @@ -421,10 +427,10 @@ class Link { case '22': case '23': case '24': - //TODO: Alter Code, umstellen auf JS Client von RO. Vorlage koennte 'Delete' in Subrecord sein. - $link = "<a href=\"javascript: void(0);\" onClick=\"var del = new FR.Delete({recordId:'',sip:'',forward:'" . - $vars[NAME_PAGE] . "'});\" " . $vars[NAME_LINK_CLASS] . ">" . $vars[NAME_TEXT] . "</a>"; - break; + //TODO: Alter Code, umstellen auf JS Client von RO. Vorlage koennte 'Delete' in Subrecord sein. + $link = "<a href=\"javascript: void(0);\" onClick=\"var del = new FR.Delete({recordId:'',sip:'',forward:'" . + $vars[NAME_PAGE] . "'});\" " . $vars[NAME_LINK_CLASS] . ">" . $vars[NAME_TEXT] . "</a>"; + break; // 5: plain text, no <span> around case '5': @@ -442,7 +448,9 @@ class Link { case '26': throw new UserReportException ("Mode not implemented. internal render mode=$mode", ERROR_UNKNOWN_MODE); break; - + case '8': + $link = substr($vars[FINAL_HREF],12); // strip 'index.php?s=' + break; default: throw new UserReportException ("Mode not implemented. internal render mode=$mode", ERROR_UNKNOWN_MODE); @@ -1321,7 +1329,7 @@ EOF; // if ($vars[NAME_BOOTSTRAP_BUTTON] == '0') { // $vars[NAME_EXTRA_CONTENT_WRAP] = '<button type="button" ' . $attributes . $onClick . '>'; // } else { - $vars[NAME_EXTRA_CONTENT_WRAP] = '<span ' . $attributes . $onClick . '>'; + $vars[NAME_EXTRA_CONTENT_WRAP] = '<span ' . $attributes . $onClick . '>'; $vars[NAME_BOOTSTRAP_BUTTON] = '0'; // } diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php index 6c44a55ce5723e5c50cd22bcb170773563f3bad0..1afd6c4fd33f2b5b544f1e7d6e9ad9c83e760b59 100644 --- a/extension/qfq/qfq/report/Report.php +++ b/extension/qfq/qfq/report/Report.php @@ -668,6 +668,7 @@ class Report { * @return string rendered column * @throws CodeException * @throws DbException + * @throws DownloadException * @throws UserFormException * @throws UserReportException */ @@ -709,10 +710,10 @@ class Report { case COLUMN_PPAGEI: case COLUMN_PPAGEN: case COLUMN_PPAGES: - $lowerColumnName = strtolower($columnName); + $lowerColumnName = strtolower($columnName); $tokenizedValue = $this->doFixColPosPage($columnName, $columnValue); - $linkValue = $this->doPage($lowerColumnName, $tokenizedValue); - $content .= $this->link->renderLink($linkValue); + $linkValue = $this->doPage($lowerColumnName, $tokenizedValue); + $content .= $this->link->renderLink($linkValue); break; // Lowercase 'P' @@ -725,7 +726,7 @@ class Report { case COLUMN_PAGEN: case COLUMN_PAGES: $linkValue = $this->doPage($columnName, $columnValue); - $content .= $this->link->renderLink($linkValue); + $content .= $this->link->renderLink($linkValue); break; case COLUMN_PPDF: diff --git a/extension/qfq/qfq/store/FillStoreForm.php b/extension/qfq/qfq/store/FillStoreForm.php index 9eadf27730d98b3f8f8f3bc9f3434bedfef804c6..d2f435afefcd08a6a8df35d7b151d66f9b256c8f 100644 --- a/extension/qfq/qfq/store/FillStoreForm.php +++ b/extension/qfq/qfq/store/FillStoreForm.php @@ -81,7 +81,7 @@ class FillStoreForm { // Preparation for Log, Debug $this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM); - $feSpecNative = $this->dbArray[$this->dbIndexQfq]->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_EXPECT_GE_1, [$formName], + $feSpecNative = $this->dbArray[$this->dbIndexQfq]->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_REGULAR, [$formName], 'Form or FormElements not found: ' . ERROR_FORM_NOT_FOUND); HelperFormElement::explodeParameterInArrayElements($feSpecNative, FE_PARAMETER);