From 45d2a426b3767db79f0bb33293f4185ba6791178 Mon Sep 17 00:00:00 2001
From: Daniel Siepmann <daniel.siepmann@typo3.org>
Date: Tue, 12 May 2020 17:40:58 +0200
Subject: [PATCH] [BUGFIX] Open CSH with selected context provided by links

A context can be provided, when opening the CSH (Context Sensitive Help).

E.g. when opening the CSH for a backend module or specific table field,
the help entry for that module or field will be opened.

This patch restores the described functionality by adding the action
to the link opened via JavaScript.

The "see also" links, used for cross referencing different CSH entries
are fixed as well. Cross referencing links are now build using the proper
ViewHelper to use backend module routing, instead of extbase routing.
This ensures arguments are not moved into an arbitrary extbase plugin
namespace.

Resolves: #91370
Releases: master
Change-Id: Ib6361e5a5f4ef441e098a595fa344f484a07ddc0
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64477
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Josef Glatz <josefglatz@gmail.com>
Reviewed-by: Sebastian Klein <laitnin@gmx.net>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Sebastian Klein <laitnin@gmx.net>
Tested-by: Josef Glatz <josefglatz@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
---
 .../Public/TypeScript/ContextHelp.ts          |  3 +-
 .../Repository/TableManualRepository.php      |  3 +-
 .../Partials/ContextSensitiveHelp/Manual.html | 81 ++++++++++---------
 .../Public/JavaScript/ContextHelp.js          |  2 +-
 4 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextHelp.ts b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextHelp.ts
index 3328d6668885..b09b18a91a10 100644
--- a/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextHelp.ts
+++ b/Build/Sources/TypeScript/backend/Resources/Public/TypeScript/ContextHelp.ts
@@ -127,7 +127,8 @@ class ContextHelp {
       const cshWindow = window.open(
         this.helpModuleUrl +
         '&table=' + $trigger.data('table') +
-        '&field=' + $trigger.data('field'),
+        '&field=' + $trigger.data('field') +
+        '&action=detail',
         'ContextHelpWindow',
         'height=400,width=600,status=0,menubar=0,scrollbars=1',
       );
diff --git a/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php b/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php
index e1b709af65cb..be427688a1db 100644
--- a/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php
+++ b/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php
@@ -306,7 +306,8 @@ class TableManualRepository
                                 'internal' => true,
                                 'arguments' => [
                                     'table' => $table,
-                                    'field' => $field
+                                    'field' => $field,
+                                    'action' => 'detail',
                                 ],
                                 'title' => $label
                             ];
diff --git a/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html b/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html
index e08b0830bf12..5d60234b3f76 100644
--- a/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html
+++ b/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html
@@ -1,45 +1,48 @@
-<a id="{manual.table}{f:if(condition:manual.field,then:'.{manual.field}')}"></a>
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+    xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
+    data-namespace-typo3-fluid="true">
+    <a id="{manual.table}{f:if(condition:manual.field,then:'.{manual.field}')}"></a>
 
-<h2>{manual.headerLine}</h2>
-<p>{manual.content -> f:format.htmlentities() -> f:format.raw()}</p>
+    <h2>{manual.headerLine}</h2>
+    <p>{manual.content -> f:format.htmlentities() -> f:format.raw()}</p>
 
-<f:if condition="{manual.configuration.details}">
-    <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:details" /></h3>
-    <p>{manual.configuration.details -> f:format.stripTags(allowedTags:'<strong><em><b><i>') -> f:format.nl2br()}</p>
-</f:if>
+    <f:if condition="{manual.configuration.details}">
+        <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:details" /></h3>
+        <p>{manual.configuration.details -> f:format.stripTags(allowedTags:'<strong><em><b><i>') -> f:format.nl2br()}</p>
+    </f:if>
 
-<f:if condition="{manual.configuration.syntax}">
-    <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:syntax" /></h3>
-    {manual.configuration.syntax -> f:format.raw()}
-</f:if>
+    <f:if condition="{manual.configuration.syntax}">
+        <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:syntax" /></h3>
+        {manual.configuration.syntax -> f:format.raw()}
+    </f:if>
 
-<f:if condition="{manual.images}">
-    <f:for each="{manual.images}" as="image">
-        <div>
-            <img src="../{image.image}" class="img-responsive" />
-            <f:if condition="{image.description}">
-                <p>{image.description}</p>
-            </f:if>
-        </div>
-    </f:for>
-    {manual.configuration.syntax -> f:format.raw()}
-</f:if>
-
-<f:if condition="{manual.seeAlso}">
-    <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:seeAlso" /></h3>
-    <ul>
-        <f:for each="{manual.seeAlso}" as="link">
-            <li>
-                <f:if condition="{link.internal}">
-                    <f:then>
-                        <f:link.action action="detail" arguments="{link.arguments}">{link.title}</f:link.action>
-                    </f:then>
-                    <f:else>
-                        <a href="{link.url}" target="{link.target}">{link.title}</a>
-                    </f:else>
+    <f:if condition="{manual.images}">
+        <f:for each="{manual.images}" as="image">
+            <div>
+                <img src="../{image.image}" class="img-responsive" />
+                <f:if condition="{image.description}">
+                    <p>{image.description}</p>
                 </f:if>
-
-            </li>
+            </div>
         </f:for>
-    </ul>
-</f:if>
+        {manual.configuration.syntax -> f:format.raw()}
+    </f:if>
+
+    <f:if condition="{manual.seeAlso}">
+        <h3><f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:seeAlso" /></h3>
+        <ul>
+            <f:for each="{manual.seeAlso}" as="link">
+                <li>
+                    <f:if condition="{link.internal}">
+                        <f:then>
+                            <a href="{be:moduleLink(route: 'help_cshmanual', arguments: link.arguments)}">{link.title}</a>
+                        </f:then>
+                        <f:else>
+                            <a href="{link.url}" target="{link.target}">{link.title}</a>
+                        </f:else>
+                    </f:if>
+                </li>
+            </f:for>
+        </ul>
+    </f:if>
+</html>
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.js
index ec457db4be45..07d3166f736a 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","./Popover","bootstrap"],(function(t,e,o,a,s){"use strict";class i{constructor(){this.ajaxUrl=TYPO3.settings.ajaxUrls.context_help,this.trigger="click",this.placement="auto",this.selector=".help-link",this.initialize()}static resolveBackend(){return void 0!==window.opener&&null!==window.opener?window.opener.top:top}initialize(){const t=i.resolveBackend();void 0!==t.TYPO3.settings.ContextHelp&&(this.helpModuleUrl=t.TYPO3.settings.ContextHelp.moduleUrl),void 0===TYPO3.ShortcutMenu&&void 0===t.TYPO3.ShortcutMenu&&o(".icon-actions-system-shortcut-new").closest(".btn").hide();let e="&nbsp;";void 0!==t.TYPO3.lang&&(e=t.TYPO3.lang.csh_tooltip_loading);const a=o(this.selector);a.attr("data-loaded","false").attr("data-html","true").attr("data-original-title",e).attr("data-placement",this.placement).attr("data-trigger",this.trigger),s.popover(a),o(document).on("show.bs.popover",this.selector,t=>{const e=o(t.currentTarget),a=e.data("description");void 0!==a&&""!==a?s.setOptions(e,{title:e.data("title"),content:a}):"false"===e.attr("data-loaded")&&e.data("table")&&this.loadHelp(e),e.closest(".t3js-module-docheader").length&&s.setOption(e,"placement","bottom")}).on("shown.bs.popover",this.selector,t=>{const e=o(t.target).data("bs.popover").$tip;e.find(".popover-title").is(":visible")||e.addClass("no-title")}).on("click",".help-has-link",t=>{o(".popover").each((e,a)=>{const s=o(a);s.has(t.target).length&&this.showHelpPopup(s.data("bs.popover").$element)})}).on("click","body",t=>{o(this.selector).each((e,a)=>{const i=o(a);i.is(t.target)||0!==i.has(t.target).length||0!==o(".popover").has(t.target).length||s.hide(i)})})}showHelpPopup(t){try{const e=window.open(this.helpModuleUrl+"&table="+t.data("table")+"&field="+t.data("field"),"ContextHelpWindow","height=400,width=600,status=0,menubar=0,scrollbars=1");return e.focus(),s.hide(t),e}catch(t){}}loadHelp(t){const e=t.data("table"),o=t.data("field");e&&new a(this.ajaxUrl).withQueryArguments({params:{action:"getContextHelp",table:e,field:o}}).get().then(async e=>{const o=await e.resolve(),a=o.title||"",i=o.content||"<p></p>";s.setOptions(t,{title:a,content:i}),t.attr("data-loaded","true").one("hidden.bs.popover",()=>{s.show(t)}),s.hide(t)})}}return new i}));
\ No newline at end of file
+define(["require","exports","jquery","TYPO3/CMS/Core/Ajax/AjaxRequest","./Popover","bootstrap"],(function(t,e,o,a,s){"use strict";class i{constructor(){this.ajaxUrl=TYPO3.settings.ajaxUrls.context_help,this.trigger="click",this.placement="auto",this.selector=".help-link",this.initialize()}static resolveBackend(){return void 0!==window.opener&&null!==window.opener?window.opener.top:top}initialize(){const t=i.resolveBackend();void 0!==t.TYPO3.settings.ContextHelp&&(this.helpModuleUrl=t.TYPO3.settings.ContextHelp.moduleUrl),void 0===TYPO3.ShortcutMenu&&void 0===t.TYPO3.ShortcutMenu&&o(".icon-actions-system-shortcut-new").closest(".btn").hide();let e="&nbsp;";void 0!==t.TYPO3.lang&&(e=t.TYPO3.lang.csh_tooltip_loading);const a=o(this.selector);a.attr("data-loaded","false").attr("data-html","true").attr("data-original-title",e).attr("data-placement",this.placement).attr("data-trigger",this.trigger),s.popover(a),o(document).on("show.bs.popover",this.selector,t=>{const e=o(t.currentTarget),a=e.data("description");void 0!==a&&""!==a?s.setOptions(e,{title:e.data("title"),content:a}):"false"===e.attr("data-loaded")&&e.data("table")&&this.loadHelp(e),e.closest(".t3js-module-docheader").length&&s.setOption(e,"placement","bottom")}).on("shown.bs.popover",this.selector,t=>{const e=o(t.target).data("bs.popover").$tip;e.find(".popover-title").is(":visible")||e.addClass("no-title")}).on("click",".help-has-link",t=>{o(".popover").each((e,a)=>{const s=o(a);s.has(t.target).length&&this.showHelpPopup(s.data("bs.popover").$element)})}).on("click","body",t=>{o(this.selector).each((e,a)=>{const i=o(a);i.is(t.target)||0!==i.has(t.target).length||0!==o(".popover").has(t.target).length||s.hide(i)})})}showHelpPopup(t){try{const e=window.open(this.helpModuleUrl+"&table="+t.data("table")+"&field="+t.data("field")+"&action=detail","ContextHelpWindow","height=400,width=600,status=0,menubar=0,scrollbars=1");return e.focus(),s.hide(t),e}catch(t){}}loadHelp(t){const e=t.data("table"),o=t.data("field");e&&new a(this.ajaxUrl).withQueryArguments({params:{action:"getContextHelp",table:e,field:o}}).get().then(async e=>{const o=await e.resolve(),a=o.title||"",i=o.content||"<p></p>";s.setOptions(t,{title:a,content:i}),t.attr("data-loaded","true").one("hidden.bs.popover",()=>{s.show(t)}),s.hide(t)})}}return new i}));
\ No newline at end of file
-- 
GitLab