diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index 0bb933fbd4ce407233736bcc306dcc609ef183ac..e65c45daa1f6431084142defa0cc690f8c605b7a 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -2935,7 +2935,7 @@ Type: radio * *itemList* = `<attribute>` E.g.: *itemList=red,blue,orange* or *itemList=1:red,2:blue,3:orange* * If ':' or ',' are part of key or value, it needs to escaped by '\\'. - E.g.: `itemList=1:red\\: (with colon),2:blue\\, (with comma),3:orange`` + E.g.: `itemList=1:red\\: (with colon),2:blue\\, (with comma),3:orange` 3. Definition of the *enum* or *set* field (only labels, ids are not possible). @@ -3137,6 +3137,8 @@ and will be processed after saving the primary record and before any action Form {{SELECT SUBSTRING_INDEX( '{{pathFileName:R}}', '/', -1) }} +See also `downloadButton`_ to offer a download of an uploaded file. + * *FormElement.parameter*: * *capture=camera*: On a smartphone, after pressing the 'open file' button, the camera will be opened and a @@ -3185,6 +3187,15 @@ and will be processed after saving the primary record and before any action Form * *fileReplace=always*: If `fileDestination` exist - replace it by the new one. +.. _`downloadButton`: + + * *downloadButton*: If given, shows a button to download the previous uploaded file - instead of the string given in + `fe.value`. It's important that `fe.value` points to a readable file on the server. + + If `downloadButton` ist empty, just shows the regular download glyph. + + Additional attributes might be given like `downloadButton='t:Download|o:check file'. Please check `download`_. + * fileSplit, fileDestinationSplit, tableNameSplit: see split-pdf-upload_ Immediately after the upload finished (before the user press save), the file will be checked on the server for it's @@ -5041,23 +5052,23 @@ Parameter and (element) sources * *popupMessage*: `a:<text>` - will be displayed in the popup window during download. If the creating/download is fast, the window might disappear quickly. -* *mode*: `m:<mode>` +* *mode*: `M:<mode>` * *mode* = <file | pdf | zip> - This parameter is optional and can be skipped in most situations. Mandatory for 'zip'. - * If `m:file`, the mime type is derived dynamically from the specified file. In this mode, only one element source + * If `M:file`, the mime type is derived dynamically from the specified file. In this mode, only one element source is allowed per download link (no concatenation). * In case of multiple element sources, only `pdf` or `zip` is supported. - * If `m:zip` is used together with `p:...`, `U:...` or `u:..`, those HTML pages will be converted to PDF. Those files + * If `M:zip` is used together with `p:...`, `U:...` or `u:..`, those HTML pages will be converted to PDF. Those files get generic filenames inside the archive. * If not specified, the **default** 'Mode' depends on the number of specified element sources (=file or web page): * If only one `file` is specifed, the default is `file`. * If there is a) a page defined or b) multiple elements, the default is `pdf`. -* *element sources* - for `m:pdf` or `m:zip`, all of the following three element sources might be specified multiple times. Any combination and order of the three options are allowed. +* *element sources* - for `M:pdf` or `M:zip`, all of the following three element sources might be specified multiple times. Any combination and order of the three options are allowed. * *file*: `F:<pathFileName>` - relative or absolute pathFileName offered for a) download (single), or to be concatenated in a PDF or ZIP. @@ -5093,7 +5104,7 @@ Example `_link`: :: SELECT "d:file.pdf|s|t:Download|F:fileadmin/pdf/test.pdf" AS _link # single `file`, with mode - SELECT "d:file.pdf|m:pdf|s|t:Download|F:fileadmin/pdf/test.pdf" AS _link + SELECT "d:file.pdf|M:pdf|s|t:Download|F:fileadmin/pdf/test.pdf" AS _link # three sources: two pages and one file SELECT "d:complete.pdf|s|t:Complete PDF|p:id=detail&r=1|p:id=detail2&r=1|F:fileadmin/pdf/test.pdf" AS _link diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php index 14bdb57f28afd8190621779fc4ce86d8453f0215..4cb1527719a69357bb39170779ca9d7d7ad36531 100644 --- a/extension/qfq/qfq/AbstractBuildForm.php +++ b/extension/qfq/qfq/AbstractBuildForm.php @@ -2891,7 +2891,16 @@ abstract class AbstractBuildForm { Support::setIfNotSet($formElement, FE_FILE_BUTTON_TEXT, FE_FILE_BUTTON_TEXT_DEFAULT); $htmlInputFile = Support::wrapTag("<label $attributeFileLabel>", $htmlInputFile . $formElement[FE_FILE_BUTTON_TEXT]); - $deleteButton = Support::wrapTag("<button type='button' class='delete-file' data-sip='$sipUpload' name='delete-$htmlFormElementName'>", $this->symbol[SYMBOL_DELETE]); + $deleteButton = Support::wrapTag("<button type='button' class='btn btn-default delete-file' data-sip='$sipUpload' name='delete-$htmlFormElementName'>", $this->symbol[SYMBOL_DELETE]); + + if (Support::isEnabled($formElement, FE_FILE_DOWNLOAD_BUTTON)) { + if (is_readable($value)) { + $link = new Link($this->sip); + $value = $link->renderLink('s|M:file|d|F:' . $value . '|' . $formElement[FE_FILE_DOWNLOAD_BUTTON]); + } else { + $value .= " - file not found, please check field 'value'"; + } + } $htmlFilename = Support::wrapTag("<span class='uploaded-file-name'>", $value, false); $htmlTextDelete = Support::wrapTag("<div class='uploaded-file $textDeleteClass'>", $htmlFilename . ' ' . $deleteButton); diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php index 285e8c8345771fae54486b5392f4e212a5177bb5..ef967d7148b41053452d22f8c9f2b33ac84725fb 100644 --- a/extension/qfq/qfq/Constants.php +++ b/extension/qfq/qfq/Constants.php @@ -867,6 +867,7 @@ const FE_FILE_CAPTURE = 'capture'; // On a smartphone opens the camera const FE_FILE_SPLIT = 'fileSplit'; const FE_FILE_SPLIT_SVG = 'svg'; const FE_FILE_SPLIT_TABLE_NAME = 'tableNameSplit'; +const FE_FILE_DOWNLOAD_BUTTON = 'downloadButton'; const FE_IMAGE_SOURCE = 'imageSource'; // Image source for a fabric element const FE_SQL_VALIDATE = 'sqlValidate'; // Action: Query to validate form load diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php index e0522e5dc1b38dcc07da2ac72ad59a84127797b6..360ac548a279f37a9f9f54c29bfd913e3e866a43 100644 --- a/extension/qfq/qfq/helper/Support.php +++ b/extension/qfq/qfq/helper/Support.php @@ -930,7 +930,7 @@ class Support { } /** - * Convert 'false' and 'empty' to '0'. + * Convert 'false' and '<empty string>' to '0'. * * @param $val * @@ -940,6 +940,25 @@ class Support { return ($val == '' || $val == false) ? '0' : $val; } + /** + * If there is an element $key in array $arr and if that is empty (acts as a switch) or not equal '0': return true, else false + * + * @param array $arr + * @param string $key + * @return bool true: if $key exists and a) is empty or b) =='1' + */ + public static function isEnabled(array $arr, $key) { + if (!array_key_exists($key, $arr)) { + return false; + } + + if ($arr[$key] === '' || $arr[$key] !== '0') { + return true; + } else { + return false; + } + } + /** * Check if the string starts with the comment sign - return an empty string. * Check if the string starts with an escaped comment sign - strip the escape character. diff --git a/extension/qfq/tests/phpunit/SupportTest.php b/extension/qfq/tests/phpunit/SupportTest.php index 83efd041b4d591ddb6a2d1ce8bad6566d8dd2a1a..52a38cb0ebb0636d06fc5b357f768655adf177b4 100644 --- a/extension/qfq/tests/phpunit/SupportTest.php +++ b/extension/qfq/tests/phpunit/SupportTest.php @@ -467,6 +467,29 @@ class SupportTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('<div class="qfq" class="123">', $new); } + public function testFalseEmptyToZero() { + $this->assertEquals('0', Support::falseEmptyToZero('')); + $this->assertEquals('0', Support::falseEmptyToZero(false)); + $this->assertEquals('false', Support::falseEmptyToZero('false')); + $this->assertEquals('true', Support::falseEmptyToZero('true')); + $this->assertEquals('123', Support::falseEmptyToZero('123')); + } + + public function testIsEnabled() { + $this->assertEquals(false, Support::isEnabled(array(), '')); + $this->assertEquals(false, Support::isEnabled(array(), 'test')); + $this->assertEquals(false, Support::isEnabled(['test' => '0'], 'test')); + + $this->assertEquals(true, Support::isEnabled(['test' => ''], 'test')); + $this->assertEquals(true, Support::isEnabled(['test' => 'val'], 'test')); + $this->assertEquals(true, Support::isEnabled(['test' => '1'], 'test')); + + $this->assertEquals(false, Support::isEnabled(['a' => '1', 'b' => '2', 'c' => '3'], 'test')); + $this->assertEquals(true, Support::isEnabled(['a' => '1', 'b' => '2', 'c' => '3'], 'a')); + $this->assertEquals(true, Support::isEnabled(['a' => '1', 'b' => '2', 'c' => '3'], 'b')); + $this->assertEquals(false, Support::isEnabled(['a' => '1', 'b' => '0', 'c' => '3'], 'b')); + } + public function testunEscapeNComment() { $this->assertEquals('', Support::handleEscapeSpaceComment(''));