From c3afadfe96b72e44fcc931acd7c63b6f0942e2cf Mon Sep 17 00:00:00 2001
From: Carsten  Rose <carsten.rose@math.uzh.ch>
Date: Sun, 29 Jan 2017 21:54:58 +0100
Subject: [PATCH] Link.php, Report.php: New '_link' token 'x'. '_paged' and
 '_Paged' are rendered via Link() class, Link() class now supports delete
 links.

---
 extension/Documentation/UsersManual/Index.rst | 108 +++++++++---------
 extension/qfq/qfq/report/Link.php             | 101 +++++++++++++++-
 extension/qfq/qfq/report/Report.php           |  80 ++++++-------
 extension/qfq/tests/phpunit/LinkTest.php      |  58 +++++++++-
 4 files changed, 248 insertions(+), 99 deletions(-)

diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst
index 01d9464ba..4c3824002 100644
--- a/extension/Documentation/UsersManual/Index.rst
+++ b/extension/Documentation/UsersManual/Index.rst
@@ -1614,55 +1614,57 @@ Column: _link
 * Column names like `_pagee`, `_mailto`, ... are wrapper to class link.
 * The parameters for link contains a prefix to make them position-independet.
 
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|URL|IMG|Meaning   |Qualifier                          |Example                    |Description                                                                                                                             |
-+===+===+==========+===================================+===========================+========================================================================================================================================+
-|x  |   |URL       |u:<url>                            |u:http://www.example.com   |If an image is specified, it will be rendered inside the link, default link class: external                                             |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|x  |   |Mail      |m:<email>                          |m:info@example.com         |Default link class: email                                                                                                               |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|x  |   |Page      |p:<pageId>                         |p:impressum                |Prepend '?' or '?id=', no hostname qualifier (automatically set by browser), default link class: internal, default value: {{pageId}}    |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Text      |t:<text>                           |t:Firstname Lastname       |-                                                                                                                                       |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Render    |r:<mode>                           |r:[0-5]                    |See: `render-mode`_, Default: 0                                                                                                         |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Picture   |P:<filename>                       |P:bullet-red.gif           |Picture '<img src="bullet-red.gif"alt="....">', default link class: internal.                                                           |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Edit      |E                                  |E                          |Show 'edit' icon as image                                                                                                               |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |New       |N                                  |N                          |Show 'new' icon as image                                                                                                                |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Delete    |D                                  |D                          |Show 'delete' icon as image (only the icon, no database record 'delete' functionality)                                                  |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Help      |H                                  |H                          |Show 'help' icon as image                                                                                                               |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Info      |I                                  |I                          |Show 'information' icon as image                                                                                                        |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Show      |S                                  |S                          |Show 'show' icon as image                                                                                                               |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Bullet    |B:[<color>]                        |B:green                    |Show bullet with '<color>'. Colors: blue, gray, green, pink, red, yellow. Default Color: green.                                         |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |x  |Check     |C:[<color>]                        |C:green                    |Show checked with '<color>'. Colors: blue, gray, green, pink, red, yellow. Default Color: green.                                        |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |URL Params|U:<key1>=<value1>[&<keyN>=<valueN>]|U:a=value1&b=value2&c=...  |Any number of additional Params. Links to forms: U:form=Person&r=1234                                                                   |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Tooltip   |o:<text>                           |o:More information here    |Tooltip text                                                                                                                            |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Alttext   |a:<text>                           |a:Name of person           |Alttext for images                                                                                                                      |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Class     |c:[n|i|e|<text>]                   |c:i                        |CSS class for link. n:no class attribut, i:internal (ext_localconf.php)(default), e:external (ext_localconf.php), <text>: explicit named|
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Target    |g:<text>                           |g:_blank                   |target=_blank,_self,_parent,<custom>. Default: no target                                                                                |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Question  |q:<text>                           |q:please confirm           |See: `question`_. Link will be executed only if user clicks ok/cancel, default: 'Please confirm'                                        |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Encryption|e:0|1|...                          |e:1                        |Encryption of the e-mail: 0: no encryption, 1:via Javascript (default)                                                                  |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |Right     |R                                  |R                          |Defines picture position: Default is 'left' (no definition) of the 'text'. 'R' means 'right' of the 'text'                              |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
-|   |   |SIP       |s[:0|1]                            |s, s:0, s:1                |If 's' or 's:1' a SIP entry is generated with all non Typo 3 Parameters. The URL contains only parameter 's' and Typo 3 parameter       |
-+---+---+----------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|URL|IMG|Meaning       |Qualifier                          |Example                    |Description                                                                                                                             |
++===+===+==============+===================================+===========================+========================================================================================================================================+
+|x  |   |URL           |u:<url>                            |u:http://www.example.com   |If an image is specified, it will be rendered inside the link, default link class: external                                             |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|x  |   |Mail          |m:<email>                          |m:info@example.com         |Default link class: email                                                                                                               |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|x  |   |Page          |p:<pageId>                         |p:impressum                |Prepend '?' or '?id=', no hostname qualifier (automatically set by browser), default link class: internal, default value: {{pageId}}    |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Text          |t:<text>                           |t:Firstname Lastname       |-                                                                                                                                       |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Render        |r:<mode>                           |r:[0-5]                    |See: `render-mode`_, Default: 0                                                                                                         |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Picture       |P:<filename>                       |P:bullet-red.gif           |Picture '<img src="bullet-red.gif"alt="....">', default link class: internal.                                                           |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Edit          |E                                  |E                          |Show 'edit' icon as image                                                                                                               |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |New           |N                                  |N                          |Show 'new' icon as image                                                                                                                |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Delete        |D                                  |D                          |Show 'delete' icon as image (only the icon, no database record 'delete' functionality)                                                  |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Help          |H                                  |H                          |Show 'help' icon as image                                                                                                               |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Info          |I                                  |I                          |Show 'information' icon as image                                                                                                        |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Show          |S                                  |S                          |Show 'show' icon as image                                                                                                               |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Bullet        |B:[<color>]                        |B:green                    |Show bullet with '<color>'. Colors: blue, gray, green, pink, red, yellow. Default Color: green.                                         |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |x  |Check         |C:[<color>]                        |C:green                    |Show checked with '<color>'. Colors: blue, gray, green, pink, red, yellow. Default Color: green.                                        |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |URL Params    |U:<key1>=<value1>[&<keyN>=<valueN>]|U:a=value1&b=value2&c=...  |Any number of additional Params. Links to forms: U:form=Person&r=1234                                                                   |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Tooltip       |o:<text>                           |o:More information here    |Tooltip text                                                                                                                            |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Alttext       |a:<text>                           |a:Name of person           |Alttext for images                                                                                                                      |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Class         |c:[n|i|e|<text>]                   |c:i                        |CSS class for link. n:no class attribut, i:internal (ext_localconf.php)(default), e:external (ext_localconf.php), <text>: explicit named|
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Target        |g:<text>                           |g:_blank                   |target=_blank,_self,_parent,<custom>. Default: no target                                                                                |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Question      |q:<text>                           |q:please confirm           |See: `question`_. Link will be executed only if user clicks ok/cancel, default: 'Please confirm'                                        |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Encryption    |e:0|1|...                          |e:1                        |Encryption of the e-mail: 0: no encryption, 1:via Javascript (default)                                                                  |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Right         |R                                  |R                          |Defines picture position: Default is 'left' (no definition) of the 'text'. 'R' means 'right' of the 'text'                              |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |SIP           |s[:0|1]                            |s, s:0, s:1                |If 's' or 's:1' a SIP entry is generated with all non Typo 3 Parameters. The URL contains only parameter 's' and Typo 3 parameter       |
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|   |   |Delete record | x[:a|r|c]                         |x, x:r, x:c                |a: ajax (only QFQ internal used), r: report (default), c: close (current page, open last page)
++---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
 
 .. _render-mode:
 
@@ -1724,6 +1726,10 @@ Link Examples
 +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
 |SELECT "p:form_person|C:green" AS _link                                |<a class="internal" href="?form_person"><img alttext="Check" src="typo3conf/ext/qfq/Resources/Public/icons/checked-green.gif"></a>      |
 +-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|SELECT "U:form=Person&r=123|x|D" as _link                              |<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234"><span class="glyphicon glyphicon-trash" ></span>"></a>                   |
++-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
+|SELECT "U:form=Person&r=123|x|t:Delete" as _link                       |<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234">Delete</a>                                                               |
++-----------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
 
 .. _question:
 
@@ -1798,7 +1804,7 @@ The colum name is composed of the string *page* and a trailing character to spec
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
 |_pagec         |Internal link without a grafic, with question  |*Please confirm!*                    |p:<pageId>[&param]                            |
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
-|_paged         |Internal link with delete icon (trash)         |*Delete record ?*                    |U:form=<formname>&r=<recordid> or             |
+|_paged         |Internal link with delete icon (trash)         |*Delete record ?*                    |U:form=<formname>&r=<recordid> *or*           |
 |               |                                               |                                     |U:table=<tablename>&r=<recordid>              |
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
 |_pagee         |Internal link with edit icon (pencil)          |empty                                |p:<pageId>[&param]                            |
@@ -1843,7 +1849,7 @@ Column: _paged
 ^^^^^^^^^^^^^^
 
 These column offers a link, with a confirmation question, to delete one record (mode 'table') or a bunch of records
-(mode 'form'). After deleting the record(s), the current page will refreshed in the browser.
+(mode 'form'). After deleting the record(s), the current page will be reloaded in the browser.
 
 **Syntax**
 
diff --git a/extension/qfq/qfq/report/Link.php b/extension/qfq/qfq/report/Link.php
index 23ea0a323..9a39d2ded 100644
--- a/extension/qfq/qfq/report/Link.php
+++ b/extension/qfq/qfq/report/Link.php
@@ -85,6 +85,7 @@ const NAME_ENCRYPTION = 'encryption';
 const NAME_SIP = 'sip';
 const NAME_URL_PARAM = 'param';
 const NAME_RIGHT = 'picturePositionRight';
+const NAME_ACTION_DELETE = 'actionDelete';
 
 const FINAL_HREF = 'finalHref';
 const FINAL_ANCHOR = 'finalAnchor';
@@ -118,6 +119,11 @@ const TOKEN_SIP = 's';
 const TOKEN_URL_PARAM = 'U';
 const TOKEN_RIGHT = 'R';
 
+const TOKEN_ACTION_DELETE = 'x';
+const TOKEN_ACTION_DELETE_AJAX = 'a';
+const TOKEN_ACTION_DELETE_REPORT = 'r';
+const TOKEN_ACTION_DELETE_CLOSE = 'c';
+
 const TOKEN_CLASS_NONE = 'n';
 const TOKEN_CLASS_INTERNAL = 'i';
 const TOKEN_CLASS_EXTERNAL = 'e';
@@ -132,6 +138,7 @@ const DEFAULT_CHECK_COLOR = 'green';
 const DEFAULT_RENDER_MODE = '0';
 const DEFAULT_QUESTION_TEXT = 'Please confirm';
 const DEFAULT_QUESTION_LEVEL = 'info';
+const DEFAULT_ACTION_DELETE = 'r';
 
 const QUESTION_INDEX_TEXT = 0;
 const QUESTION_INDEX_LEVEL = 1;
@@ -181,7 +188,8 @@ class Link {
         TOKEN_PICTURE => 'buildPicture',
         TOKEN_BULLET => 'buildBullet',
         TOKEN_CHECK => 'buildCheck',
-        TOKEN_DELETE => 'buildDelete',
+        TOKEN_DELETE => 'buildDeleteIcon',
+        TOKEN_ACTION_DELETE => 'buildActionDelete',
         TOKEN_EDIT => 'buildEdit',
         TOKEN_HELP => 'buildHelp',
         TOKEN_INFO => 'buildInfo',
@@ -213,6 +221,7 @@ class Link {
         TOKEN_SIP => NAME_SIP,
         TOKEN_URL_PARAM => NAME_URL_PARAM,
         TOKEN_RIGHT => NAME_RIGHT,
+        TOKEN_ACTION_DELETE => NAME_ACTION_DELETE,
     ];
 
     private $tokenMapping = [
@@ -238,6 +247,11 @@ class Link {
      */
     public function __construct(Sip $sip, $phpUnit = false) {
         $this->phpUnit = $phpUnit;
+
+        if ($phpUnit) {
+            $_SERVER['REQUEST_URI'] = 'localhost';
+        }
+
         $this->sip = $sip;
         $this->store = Store::getInstance('', $phpUnit);
         $this->cssLinkClassInternal = $this->store->getVar(SYSTEM_CSS_LINK_CLASS_INTERNAL, STORE_SYSTEM);
@@ -471,6 +485,8 @@ class Link {
             NAME_LINK_CLASS => '', // class name
             NAME_LINK_CLASS_DEFAULT => '', // Depending of 'as page' or 'as url'. Only used if class is not explizit set.
 
+            NAME_ACTION_DELETE => '',
+
             FINAL_HREF => '',
             FINAL_CONTENT => '',
             FINAL_SYMBOL => '',
@@ -482,6 +498,8 @@ class Link {
     }
 
     /**
+     * Verify Empty values. If appropriate, set defaults, if not throw anexception.
+     *
      * @param $key
      * @param $value
      * @return string
@@ -513,6 +531,9 @@ class Link {
             case TOKEN_RENDER:
                 $value = DEFAULT_RENDER_MODE;
                 break;
+            case TOKEN_ACTION_DELETE:
+                $value = DEFAULT_ACTION_DELETE;
+                break;
             default:
         }
 
@@ -520,6 +541,8 @@ class Link {
     }
 
     /**
+     * Validate value for token
+     *
      * @param $key
      * @param $value
      * @return mixed
@@ -533,6 +556,16 @@ class Link {
                     throw new UserReportException ("Invalid value for token '$key': '$value''", ERROR_INVALID_VALUE);
                 }
                 break;
+            case TOKEN_ACTION_DELETE:
+                switch ($value) {
+                    case TOKEN_ACTION_DELETE_AJAX:
+                    case TOKEN_ACTION_DELETE_REPORT:
+                    case TOKEN_ACTION_DELETE_CLOSE:
+                        break;
+                    default:
+                        throw new UserReportException ("Invalid value for token '$key': '$value''", ERROR_INVALID_VALUE);
+                }
+                break;
             default:
         }
 
@@ -607,6 +640,10 @@ class Link {
     private function doHref(array &$vars) {
         $urlNParam = '';
 
+        if ($vars[NAME_ACTION_DELETE] !== '') {
+            $vars[NAME_URL_PARAM] = $this->adjustDeleteParameter($vars[NAME_ACTION_DELETE], $vars[NAME_URL_PARAM]);
+        }
+
         if ($vars[NAME_MAIL] === '') {
 
             if (substr($vars[NAME_URL], 0, 1) === '?') {
@@ -637,6 +674,41 @@ class Link {
         return $urlNParam;
     }
 
+    /**
+     * @param $tokenActionDelete
+     * @param $nameUrlParam
+     * @return string
+     * @throws UserReportException
+     */
+    private function adjustDeleteParameter($tokenActionDelete, $nameUrlParam) {
+
+        $kvp = new KeyValueStringParser();
+
+        // Split in: [p => 'r=100&table=note&..', 'D' => ''... ],
+//        $param = $kvp->parse($nameUrlParam, ':', '|');
+
+//        Support::setIfNotSet($param, TOKEN_URL_PARAM);
+
+        switch ($tokenActionDelete) {
+            case TOKEN_ACTION_DELETE_AJAX:
+                // TODO: Implement for AJAX (subrecord)
+                throw new UserReportException ("Not implemented!", ERROR_NOT_IMPLEMENTED);
+                break;
+            case TOKEN_ACTION_DELETE_REPORT:
+                $nameUrlParam .= '&' . SIP_MODE_ANSWER . '=' . MODE_HTML;
+                $nameUrlParam .= '&' . SIP_TARGET_URL . '=' . $_SERVER['REQUEST_URI'];
+                break;
+            case TOKEN_ACTION_DELETE_CLOSE:
+                // TODO: Implement for Form (primary Record wird geloescht)
+                throw new UserReportException ("Not implemented!", ERROR_NOT_IMPLEMENTED);
+                break;
+            default:
+                throw new UserReportException ("Invalid value for token '" . TOKEN_ACTION_DELETE . "': '$tokenActionDelete''", ERROR_INVALID_VALUE);
+        }
+
+        return $nameUrlParam;
+    }
+
     /**
      * Return $vars[NAME_TOOL_TIP]. If $vars[NAME_TOOL_TIP] is empty, set $vars[NAME_GLYPH_TITLE] as tooltip.
      *
@@ -1044,15 +1116,39 @@ EOF;
      * @param $vars
      * @return array
      */
-    private function buildDelete($vars) {
+    private function buildDeleteIcon($vars) {
 
         $vars[NAME_GLYPH] = GLYPH_ICON_DELETE;
         $vars[NAME_GLYPH_TITLE] = "Delete";
         $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS;
 
+        return $vars;
+    }
+
+    /**
+     * Called by $this->callTable
+     *
+     * @param $vars
+     * @param $value
+     * @return array
+     * @throws UserReportException
+     */
+    private function buildActionDelete($vars, $value) {
+
         // Minimal check for required parameter.
         $this->checkDeleteParam($vars[NAME_URL_PARAM]);
 
+        if ($vars[NAME_URL] == '') {
+            $vars[NAME_URL] = API_DIR . '/' . API_DELETE_PHP;
+        }
+
+        if (!isset($vars[NAME_LINK_CLASS])) {
+            // no_class: By default a button will be rendered. NAME_URL typically implies class external. That does not match.
+            $vars[NAME_LINK_CLASS_DEFAULT] = NO_CLASS;
+        }
+
+        $vars[NAME_SIP] = "1";
+
         return $vars;
     }
 
@@ -1081,6 +1177,7 @@ EOF;
             SIP_RECORD_ID . ", " . SIP_FORM . " or " . SIP_TABLE, ERROR_MISSING_REQUIRED_DELETE_QUALIFIER);
 
     }
+
     /**
      * Called by $this->callTable
      *
diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php
index b63b389aa..b07302760 100644
--- a/extension/qfq/qfq/report/Report.php
+++ b/extension/qfq/qfq/report/Report.php
@@ -604,8 +604,9 @@ class Report {
                 break;
 
             case "bullet":
-                if ($columnValue === '')
+                if ($columnValue === '') {
                     break;
+                }
 
                 // r:3|B:
                 $linkValue = TOKEN_RENDER . ":3|" . TOKEN_BULLET . ":" . $columnValue;
@@ -613,8 +614,9 @@ class Report {
                 break;
 
             case "check":
-                if ($columnValue === '')
+                if ($columnValue === '') {
                     break;
+                }
 
                 // "r:3|C:
                 $linkValue = TOKEN_RENDER . ":3|" . TOKEN_CHECK . ":" . $columnValue;
@@ -623,8 +625,9 @@ class Report {
 
             case "img":
                 // "<path to image>|[alttext]|[text behind]" renders to: <img src="<path to image>" alt="[alttext]">[text behind]
-                if (empty($columnValue))
+                if (empty($columnValue)) {
                     break;
+                }
 
                 $mailarr = explode("|", $columnValue, 3);
 
@@ -632,8 +635,9 @@ class Report {
                 $mailarr[] = '';
                 $mailarr[] = '';
 
-                if (empty($mailarr[0]))
+                if (empty($mailarr[0])) {
                     break;
+                }
                 $attribute = Support::doAttribute('src', $mailarr[0]);
                 $attribute .= Support::doAttribute('alt', $mailarr[1]);
 
@@ -643,8 +647,9 @@ class Report {
             case "mailto":
                 // "<email address>|[Real Name]"  renders to (encrypted via JS): <a href="mailto://<email address>"><email address></a> OR <a href="mailto://<email address>">[Real Name]</a>
                 $mailarr = explode("|", $columnValue, 2);
-                if (empty($mailarr[0]))
+                if (empty($mailarr[0])) {
                     break;
+                }
 
                 $t1 = explode("@", $mailarr[0], 2);
                 $content .= "<script language=javascript><!--" . chr(10);
@@ -667,23 +672,29 @@ class Report {
                     throw new SyntaxReportException ("Too few parameter for sendmail: $columnValue", ERROR_TOO_FEW_PARAMETER_FOR_SENDMAIL, null, __FILE__, __LINE__, $this->fr_error);
                 }
 
-                if (!isset($mailarr[SENDMAIL_IDX_REPLY_TO]))
+                if (!isset($mailarr[SENDMAIL_IDX_REPLY_TO])) {
                     $mailarr[SENDMAIL_IDX_REPLY_TO] = '';
+                }
 
-                if (!isset($mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT]))
+                if (!isset($mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT])) {
                     $mailarr[SENDMAIL_IDX_FLAG_AUTO_SUBMIT] = 'off';
+                }
 
-                if (!isset($mailarr[SENDMAIL_IDX_GR_ID]))
+                if (!isset($mailarr[SENDMAIL_IDX_GR_ID])) {
                     $mailarr[SENDMAIL_IDX_GR_ID] = '0';
+                }
 
-                if (!isset($mailarr[SENDMAIL_IDX_X_ID]))
+                if (!isset($mailarr[SENDMAIL_IDX_X_ID])) {
                     $mailarr[SENDMAIL_IDX_X_ID] = '0';
+                }
 
-                if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_CC]))
+                if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_CC])) {
                     $mailarr[SENDMAIL_IDX_RECEIVER_CC] = '';
+                }
 
-                if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_BCC]))
+                if (!isset($mailarr[SENDMAIL_IDX_RECEIVER_BCC])) {
                     $mailarr[SENDMAIL_IDX_RECEIVER_BCC] = '';
+                }
 
                 $mailarr[SENDMAIL_IDX_SRC] = "Report: T3 pageId=" . $this->store->getVar('pageId', STORE_TYPO3) .
                     ", T3 ttcontentId=" . $this->store->getVar('ttcontentUid', STORE_TYPO3) .
@@ -704,8 +715,9 @@ class Report {
                 $mailarr = "width:$width; ";
 
                 # height
-                if ($arr[3])
+                if ($arr[3]) {
                     $mailarr .= "height:" . $arr[3] . "; ";
+                }
 
                 # tag
                 if ($arr[4]) {
@@ -885,12 +897,16 @@ class Report {
     private function doPage($columnName, $columnValue) {
 
         $defaultQuestion = '';
+        $defaultActionDelete = '';
 
         $param = explode('|', $columnValue);
 
         # get all defaultvalues, depending on the columnname
         $defaultImage = isset($this->pageDefaults[DEFAULT_ICON][$columnName]) ? $this->pageDefaults[DEFAULT_ICON][$columnName] : '';
         $defaultSip = 's';
+        if ($columnName === COLUMN_PAGED) {
+            $defaultActionDelete = TOKEN_ACTION_DELETE . ':' . TOKEN_ACTION_DELETE_REPORT;
+        }
 
         # define defaultquestion only, if pagetype needs a question
         if (!empty($this->pageDefaults[DEFAULT_QUESTION][$columnName])) {
@@ -916,6 +932,8 @@ class Report {
                 case TOKEN_QUESTION:
                     $defaultQuestion = '';    // if a question is given: no default
                     break;
+                case TOKEN_ACTION_DELETE:
+                    $defaultActionDelete = '';
                 default:
                     break;
             }
@@ -924,6 +942,10 @@ class Report {
         $columnValue .= "|";
 
         // append defaults
+        if ($defaultActionDelete !== '') {
+            $columnValue .= $defaultActionDelete . "|";
+        }
+
         if ($defaultImage !== '') {
             $columnValue .= $defaultImage . "|";
         }
@@ -936,41 +958,13 @@ class Report {
             $columnValue .= $defaultQuestion . "|";
         }
 
-        if ($columnName === 'paged') {
-            $columnValue = $this->adjustDeleteParameter($columnValue);
-        }
+//        if ($columnName === 'paged') {
+//            $columnValue = $this->adjustDeleteParameter($columnValue);
+//        }
 
         return ($columnValue);
     }
 
-    /**
-     * @param $columnValue
-     * @return string
-     * @throws UserFormException
-     */
-    private function adjustDeleteParameter($columnValue) {
-
-        $kvp = new KeyValueStringParser();
-
-        // Split in: [p => 'r=100&table=note&..', 'D' => ''... ],
-        $param = $kvp->parse($columnValue, ':', '|');
-
-        Support::setIfNotSet($param, TOKEN_URL_PARAM);
-
-        $param[TOKEN_URL_PARAM] .= '&' . SIP_MODE_ANSWER . '=' . MODE_HTML;
-        $param[TOKEN_URL_PARAM] .= '&' . SIP_TARGET_URL . '=' . $_SERVER['REQUEST_URI'];
-
-        if (!isset($param[TOKEN_URL])) {
-            $param[TOKEN_URL] = API_DIR . '/' . API_DELETE_PHP;
-
-            if(!isset($param[TOKEN_CLASS])) {
-                $param[TOKEN_CLASS] = TOKEN_CLASS_NONE; // no_class: By default a button will be rendered. TOKEN_URL typically implies class external. That does not match.
-            }
-        }
-
-        return $kvp->unparse($param, ':', '|');
-    }
-
     /**
      * Generate SortArgument
      *
diff --git a/extension/qfq/tests/phpunit/LinkTest.php b/extension/qfq/tests/phpunit/LinkTest.php
index e5557518a..4943875ec 100644
--- a/extension/qfq/tests/phpunit/LinkTest.php
+++ b/extension/qfq/tests/phpunit/LinkTest.php
@@ -11,6 +11,7 @@ namespace qfq;
 require_once(__DIR__ . '/../../qfq/report/Link.php');
 require_once(__DIR__ . '/../../qfq/store/Store.php');
 require_once(__DIR__ . '/../../qfq/store/Sip.php');
+require_once(__DIR__ . '/../../qfq/store/Session.php');
 
 
 class LinkTest extends \PHPUnit_Framework_TestCase {
@@ -554,9 +555,9 @@ class LinkTest extends \PHPUnit_Framework_TestCase {
         $result = $link->renderLink('u:http://example.com|N');
         $this->assertEquals('<a href="http://example.com" class="btn btn-default" title="New" ><span class="glyphicon glyphicon-plus" ></span></a>', $result);
 
-//        $result = $link->renderLink('u:http://example.com|D');
-//        $this->assertEquals('<a href="http://example.com" class="btn btn-default" title="Delete" ><span class="glyphicon glyphicon-trash" ></span></a>', $result);
-//
+        $result = $link->renderLink('u:http://example.com|D');
+        $this->assertEquals('<a href="http://example.com" class="btn btn-default" title="Delete" ><span class="glyphicon glyphicon-trash" ></span></a>', $result);
+
         $result = $link->renderLink('u:http://example.com|H');
         $this->assertEquals('<a href="http://example.com" class="btn btn-default" title="Help" ><span class="glyphicon glyphicon glyphicon-question-sign" ></span></a>', $result);
 
@@ -997,6 +998,57 @@ EOF;
 
     }
 
+
+    public function testDelete() {
+        $link = new Link($this->sip, true);
+
+        // Report Delete action, default: 'Report', no Icon
+        $result = $link->renderLink('U:form=Person&r=123|x');
+        $this->assertEquals('<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234" >typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234</a>', $result);
+        // Check das via '_paged' SIP_MODE_ANSWER and SIP_TARGET_URL has been set.
+        $result = \qfq\Session::get('badcaffee1234');
+        $this->assertEquals('_modeAnswer=html&_targetUrl=localhost&form=Person&r=123', $result);
+
+        // Report Delete action, explicit 'Report', no Icon
+        $result = $link->renderLink('U:form=PersonA&r=1234|x:r');
+        $this->assertEquals('<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234" >typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234</a>', $result);
+        // Check das via '_paged' SIP_MODE_ANSWER and SIP_TARGET_URL has been set.
+        $result = \qfq\Session::get('badcaffee1234');
+        $this->assertEquals('_modeAnswer=html&_targetUrl=localhost&form=PersonA&r=1234', $result);
+
+        // Report Delete action, explicit 'Report', Text
+        $result = $link->renderLink('U:form=PersonAa&r=2234|x:r|t:Delete Record');
+        $this->assertEquals('<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234" >Delete Record</a>', $result);
+        // Check das via '_paged' SIP_MODE_ANSWER and SIP_TARGET_URL has been set.
+        $result = \qfq\Session::get('badcaffee1234');
+        $this->assertEquals('_modeAnswer=html&_targetUrl=localhost&form=PersonAa&r=2234', $result);
+
+        // Report Delete action, with Icon
+        $result = $link->renderLink('U:form=PersonB&r=1235|x|D');
+        $this->assertEquals('<a href="typo3conf/ext/qfq/qfq/api/delete.php?s=badcaffee1234" class="btn btn-default" title="Delete" ><span class="glyphicon glyphicon-trash" ></span></a>', $result);
+        // Check das via '_paged' SIP_MODE_ANSWER and SIP_TARGET_URL has been set.
+        $result = \qfq\Session::get('badcaffee1234');
+        $this->assertEquals('_modeAnswer=html&_targetUrl=localhost&form=PersonB&r=1235', $result);
+
+        // Report Delete action: explicit php file, default: 'Report', no Icon
+        $result = $link->renderLink('u:mydelete.php|U:form=PersonC&r=1236|x');
+        $this->assertEquals('<a href="mydelete.php?s=badcaffee1234" class="external" >mydelete.php?s=badcaffee1234</a>', $result);
+        // Check das via '_paged' SIP_MODE_ANSWER and SIP_TARGET_URL has been set.
+        $result = \qfq\Session::get('badcaffee1234');
+        $this->assertEquals('_modeAnswer=html&_targetUrl=localhost&form=PersonC&r=1236', $result);
+    }
+
+    /**
+     * @expectedException \qfq\UserReportException
+     */
+    public function testDeleteException1() {
+        $link = new Link($this->sip, true);
+
+        // Missing recordId
+        $link->renderLink('U:form=Person&r=|x');
+    }
+
+
     /**
      *
      */
-- 
GitLab