[TASK] Move csh handling to backend extension 81/57381/2
authorChristian Kuhn <lolli@schwarzbu.ch>
Tue, 26 Jun 2018 19:10:15 +0000 (21:10 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Tue, 26 Jun 2018 20:11:08 +0000 (22:11 +0200)
The core and documentation team decided to drop the inline
manual view from core for various reasons that will be further
outlined with a second patch.

The documentation extension currently does both the manual
display, and also the "csh" rendering. The latter has been
merged from ext:cshmanual into ext:documentation quite
recently with core version v9.0.

The patch extracts this csh handling from ext:documentation
again and puts it into ext:backend. The patch is similar to
the v9.0 patch, only slight additions are applied along the way.
This changes also unmarks the documentation extension from
"partOfMinimalUsableSystem" since the direct dependency of
ext:backend to ext:documentation is gone with the csh merge
into backend extension.

Resolves: #85396
Related: #81574
Releases: master
Change-Id: Ib5d8f50d097696bf88f0d1e26be9cac40f1e2578
Reviewed-on: https://review.typo3.org/57381
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
38 files changed:
typo3/sysext/backend/Classes/Controller/HelpController.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Template/DocumentTemplate.php
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Migrations/Code/ClassAliasMap.php
typo3/sysext/backend/Migrations/Code/LegacyClassesForIde.php
typo3/sysext/backend/Resources/Private/Language/locallang_mod_help_cshmanual.xlf [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Language/locallang_view_help.xlf [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Layouts/ContextSensitiveHelp.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/TableOfContents.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/All.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Detail.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Index.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Public/Icons/module-cshmanual.svg [new file with mode: 0644]
typo3/sysext/backend/composer.json
typo3/sysext/backend/ext_tables.php
typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoBackend.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst [deleted file]
typo3/sysext/documentation/Classes/Controller/HelpController.php [deleted file]
typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php [deleted file]
typo3/sysext/documentation/Classes/Service/AccessService.php [deleted file]
typo3/sysext/documentation/Classes/Service/JavaScriptService.php [deleted file]
typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php [deleted file]
typo3/sysext/documentation/Migrations/Code/LegacyClassesForIde.php [deleted file]
typo3/sysext/documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf [deleted file]
typo3/sysext/documentation/Resources/Private/Language/locallang_view_help.xlf [deleted file]
typo3/sysext/documentation/Resources/Private/Layouts/ContextSensitiveHelp.html [deleted file]
typo3/sysext/documentation/Resources/Private/Partials/Manual.html [deleted file]
typo3/sysext/documentation/Resources/Private/Partials/TableOfContents.html [deleted file]
typo3/sysext/documentation/Resources/Private/Templates/Help/All.html [deleted file]
typo3/sysext/documentation/Resources/Private/Templates/Help/Detail.html [deleted file]
typo3/sysext/documentation/Resources/Private/Templates/Help/Index.html [deleted file]
typo3/sysext/documentation/Resources/Public/Icons/module-cshmanual.svg [deleted file]
typo3/sysext/documentation/composer.json
typo3/sysext/documentation/ext_localconf.php
typo3/sysext/documentation/ext_tables.php
typo3/sysext/install/Classes/Updates/BackendUserStartModuleUpdate.php

diff --git a/typo3/sysext/backend/Classes/Controller/HelpController.php b/typo3/sysext/backend/Classes/Controller/HelpController.php
new file mode 100644 (file)
index 0000000..4e9d508
--- /dev/null
@@ -0,0 +1,220 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Backend\Controller;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Domain\Repository\TableManualRepository;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
+use TYPO3\CMS\Backend\Template\ModuleTemplate;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Http\HtmlResponse;
+use TYPO3\CMS\Core\Http\RedirectResponse;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3Fluid\Fluid\View\ViewInterface;
+
+/**
+ * Main "CSH help" module controller
+ */
+class HelpController
+{
+    /**
+     * Section identifiers
+     */
+    const FULL = 0;
+
+    /**
+     * Show only Table of contents
+     */
+    const TOC_ONLY = 1;
+
+    /**
+     * @var TableManualRepository
+     */
+    protected $tableManualRepository;
+
+    /** @var ModuleTemplate */
+    protected $moduleTemplate;
+
+    /** @var ViewInterface */
+    protected $view;
+
+    /**
+     * Instantiate the report controller
+     */
+    public function __construct()
+    {
+        $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
+        $this->tableManualRepository = GeneralUtility::makeInstance(TableManualRepository::class);
+    }
+
+    /**
+     * Injects the request object for the current request, and renders correct action
+     *
+     * @param ServerRequestInterface $request the current request
+     * @return ResponseInterface the response with the content
+     */
+    public function handleRequest(ServerRequestInterface $request): ResponseInterface
+    {
+        $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'index';
+
+        if ($action === 'detail') {
+            $table = $request->getQueryParams()['table'] ?? $request->getParsedBody()['table'];
+            if (!$table) {
+                $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+                return new RedirectResponse((string)$uriBuilder->buildUriFromRoute('help_cshmanual', [
+                    'action' => 'index',
+                ]), 303);
+            }
+        }
+
+        $this->initializeView($action);
+
+        $result = call_user_func_array([$this, $action . 'Action'], [$request]);
+        if ($result instanceof ResponseInterface) {
+            return $result;
+        }
+
+        $this->registerDocheaderButtons($request);
+
+        $this->moduleTemplate->setContent($this->view->render());
+        return new HtmlResponse($this->moduleTemplate->renderContent());
+    }
+
+    /**
+     * @param string $templateName
+     */
+    protected function initializeView(string $templateName)
+    {
+        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
+        $this->view->setTemplate($templateName);
+        $this->view->setTemplateRootPaths(['EXT:backend/Resources/Private/Templates/ContextSensitiveHelp']);
+        $this->view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials']);
+        $this->view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
+        $this->view->getRequest()->setControllerExtensionName('Backend');
+        $this->view->assign('copyright', BackendUtility::TYPO3_copyRightNotice());
+    }
+
+    /**
+     * Show table of contents
+     */
+    public function indexAction()
+    {
+        $this->view->assign('toc', $this->tableManualRepository->getSections(self::TOC_ONLY));
+    }
+
+    /**
+     * Show the table of contents and all manuals
+     */
+    public function allAction()
+    {
+        $this->view->assign('all', $this->tableManualRepository->getSections(self::FULL));
+    }
+
+    /**
+     * Show a single manual
+     *
+     * @param ServerRequestInterface $request
+     */
+    public function detailAction(ServerRequestInterface $request)
+    {
+        $table = $request->getQueryParams()['table'] ?? $request->getParsedBody()['table'];
+        $field = $request->getQueryParams()['field'] ?? $request->getParsedBody()['field'] ?? '*';
+
+        $mainKey = $table;
+        $identifierParts = GeneralUtility::trimExplode('.', $field);
+        // The field is the second one
+        if (count($identifierParts) > 1) {
+            array_shift($field);
+            // There's at least one extra part
+            $extraIdentifierInformation = [];
+            $extraIdentifierInformation[] = array_shift($identifierParts);
+            // If the ds_pointerField contains a comma, it means the choice of FlexForm DS
+            // is determined by 2 parameters. In this case we have an extra identifier part
+            if (strpos($GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], ',') !== false) {
+                $extraIdentifierInformation[] = array_shift($identifierParts);
+            }
+            // The remaining parts make up the FlexForm field name itself (reassembled with dots)
+            $flexFormField = implode('.', $identifierParts);
+            // Assemble a different main key and switch field to use FlexForm field name
+            $mainKey .= '.' . $field;
+            foreach ($extraIdentifierInformation as $extraKey) {
+                $mainKey .= '.' . $extraKey;
+            }
+            $field = $flexFormField;
+        }
+
+        $this->view->assignMultiple([
+            'table' => $table,
+            'key' => $mainKey,
+            'field' => $field,
+            'manuals' => $field === '*'
+                ? $this->tableManualRepository->getTableManual($mainKey)
+                : [$this->tableManualRepository->getSingleManual($mainKey, $field)],
+        ]);
+    }
+
+    /**
+     * Registers the Icons into the docheader
+     *
+     * @param ServerRequestInterface $request
+     */
+    protected function registerDocheaderButtons(ServerRequestInterface $request)
+    {
+        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
+
+        if ($this->getBackendUser()->mayMakeShortcut()) {
+            $shortcutButton = $buttonBar->makeShortcutButton()
+                ->setModuleName('help_cshmanual')
+                ->setGetVariables(['table', 'field', 'route']);
+            $buttonBar->addButton($shortcutButton);
+        }
+
+        $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'index';
+        if ($action !== 'index') {
+            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+            $backButton = $buttonBar->makeLinkButton()
+                ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:back'))
+                ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL))
+                ->setHref((string)$uriBuilder->buildUriFromRoute('help_cshmanual'));
+            $buttonBar->addButton($backButton);
+        }
+    }
+
+    /**
+     * Returns the currently logged in BE user
+     *
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * Returns the LanguageService
+     *
+     * @return LanguageService
+     */
+    protected function getLanguageService(): LanguageService
+    {
+        return $GLOBALS['LANG'];
+    }
+}
diff --git a/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php b/typo3/sysext/backend/Classes/Domain/Repository/TableManualRepository.php
new file mode 100644 (file)
index 0000000..7528c95
--- /dev/null
@@ -0,0 +1,432 @@
+<?php
+namespace TYPO3\CMS\Backend\Domain\Repository;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Controller\HelpController;
+use TYPO3\CMS\Backend\Module\ModuleLoader;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Type\File\ImageInfo;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
+
+/**
+ * Table manual repository for csh manual handling
+ */
+class TableManualRepository
+{
+    /**
+     * Get the manual of the given table
+     *
+     * @param string $table
+     * @return array the manual for a TCA table, see getItem() for details
+     */
+    public function getTableManual($table)
+    {
+        $parts = [];
+
+        // Load descriptions for table $table
+        $this->getLanguageService()->loadSingleTableDescription($table);
+        if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $this->checkAccess('tables_select', $table)) {
+            // Reserved for header of table
+            $parts[0] = '';
+            // Traverse table columns as listed in TCA_DESCR
+            foreach ($GLOBALS['TCA_DESCR'][$table]['columns'] as $field => $_) {
+                if (!$this->isExcludableField($table, $field) || $this->checkAccess('non_exclude_fields', $table . ':' . $field)) {
+                    if (!$field) {
+                        // Header
+                        $parts[0] = $this->getItem($table, '', true);
+                    } else {
+                        // Field
+                        $parts[] = $this->getItem($table, $field, true);
+                    }
+                }
+            }
+            if (!$parts[0]) {
+                unset($parts[0]);
+            }
+        }
+        return $parts;
+    }
+
+    /**
+     * Get a single manual
+     *
+     * @param string $table table name
+     * @param string $field field name
+     * @return array
+     */
+    public function getSingleManual($table, $field)
+    {
+        $this->getLanguageService()->loadSingleTableDescription($table);
+        return $this->getItem($table, $field);
+    }
+
+    /**
+     * Get TOC sections
+     *
+     * @param string $mode
+     * @return array
+     */
+    public function getSections($mode)
+    {
+        // Initialize
+        $cshKeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
+        $tcaKeys = array_keys($GLOBALS['TCA']);
+        $outputSections = [];
+        $tocArray = [];
+        // TYPO3 Core Features
+        $lang = $this->getLanguageService();
+        $lang->loadSingleTableDescription('xMOD_csh_corebe');
+        $this->renderTableOfContentItem($mode, 'xMOD_csh_corebe', 'core', $outputSections, $tocArray, $cshKeys);
+        // Backend Modules
+        $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
+        $loadModules->load($GLOBALS['TBE_MODULES']);
+        foreach ($loadModules->modules as $mainMod => $info) {
+            $cshKey = '_MOD_' . $mainMod;
+            if ($cshKeys[$cshKey]) {
+                $lang->loadSingleTableDescription($cshKey);
+                $this->renderTableOfContentItem($mode, $cshKey, 'modules', $outputSections, $tocArray, $cshKeys);
+            }
+            if (is_array($info['sub'])) {
+                foreach ($info['sub'] as $subMod => $subInfo) {
+                    $cshKey = '_MOD_' . $mainMod . '_' . $subMod;
+                    if ($cshKeys[$cshKey]) {
+                        $lang->loadSingleTableDescription($cshKey);
+                        $this->renderTableOfContentItem($mode, $cshKey, 'modules', $outputSections, $tocArray, $cshKeys);
+                    }
+                }
+            }
+        }
+        // Database Tables
+        foreach ($tcaKeys as $table) {
+            // Load descriptions for table $table
+            $lang->loadSingleTableDescription($table);
+            if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $this->checkAccess('tables_select', $table)) {
+                $this->renderTableOfContentItem($mode, $table, 'tables', $outputSections, $tocArray, $cshKeys);
+            }
+        }
+        foreach ($cshKeys as $cshKey => $value) {
+            // Extensions
+            if (GeneralUtility::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($GLOBALS['TCA'][$cshKey])) {
+                $lang->loadSingleTableDescription($cshKey);
+                $this->renderTableOfContentItem($mode, $cshKey, 'extensions', $outputSections, $tocArray, $cshKeys);
+            }
+            // Other
+            if (!GeneralUtility::isFirstPartOfStr($cshKey, '_MOD_') && !isset($GLOBALS['TCA'][$cshKey])) {
+                $lang->loadSingleTableDescription($cshKey);
+                $this->renderTableOfContentItem($mode, $cshKey, 'other', $outputSections, $tocArray, $cshKeys);
+            }
+        }
+
+        if ($mode === HelpController::TOC_ONLY) {
+            return $tocArray;
+        }
+
+        return [
+            'toc' => $tocArray,
+            'content' => $outputSections
+        ];
+    }
+
+    /**
+     * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
+     *
+     * @param int $mode Mode
+     * @param string $table CSH key / Table name
+     * @param string $tocCat TOC category keyword: "core", "modules", "tables", "other
+     * @param array $outputSections Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
+     * @param array $tocArray TOC array; Here TOC index elements are created. Passed by reference!
+     * @param array $CSHkeys CSH keys array. Every item rendered will be unset in this array so finally we can see what CSH keys are not processed yet. Passed by reference!
+     */
+    protected function renderTableOfContentItem($mode, $table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys)
+    {
+        $tocArray[$tocCat][$table] = $this->getTableFieldLabel($table);
+        if (!$mode) {
+            // Render full manual right here!
+            $outputSections[$table]['content'] = $this->getTableManual($table);
+            if (!$outputSections[$table]) {
+                unset($outputSections[$table]);
+            }
+        }
+
+        // Unset CSH key
+        unset($CSHkeys[$table]);
+    }
+
+    /**
+     * Returns composite label for table/field
+     *
+     * @param string $key CSH key / table name
+     * @param string $field Sub key / field name
+     * @param string $mergeToken Token to merge the two strings with
+     * @return string Labels joined with merge token
+     * @see getTableFieldNames()
+     */
+    protected function getTableFieldLabel($key, $field = '', $mergeToken = ': ')
+    {
+        // Get table / field parts
+        list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
+        // Create label
+        return $this->getLanguageService()->sL($tableName) . ($field ? $mergeToken . rtrim(trim($this->getLanguageService()->sL($fieldName)), ':') : '');
+    }
+
+    /**
+     * Returns labels for a given field in a given structure
+     *
+     * @param string $key CSH key / table name
+     * @param string $field Sub key / field name
+     * @return array Table and field labels in a numeric array
+     */
+    protected function getTableFieldNames($key, $field)
+    {
+        $this->getLanguageService()->loadSingleTableDescription($key);
+        // Define the label for the key
+        if (!empty($GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'])) {
+            // If there's an alternative title, use it
+            $keyName = $GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'];
+        } elseif (isset($GLOBALS['TCA'][$key])) {
+            // Otherwise, if it's a table, use its title
+            $keyName = $GLOBALS['TCA'][$key]['ctrl']['title'];
+        } else {
+            // If no title was found, make sure to remove any "_MOD_"
+            $keyName = preg_replace('/^_MOD_/', '', $key);
+        }
+        // Define the label for the field
+        $fieldName = $field;
+        if (!empty($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'])) {
+            // If there's an alternative title, use it
+            $fieldName = $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'];
+        } elseif (!empty($GLOBALS['TCA'][$key]['columns'][$field])) {
+            // Otherwise, if it's a table, use its title
+            $fieldName = $GLOBALS['TCA'][$key]['columns'][$field]['label'];
+        }
+        return [$keyName, $fieldName];
+    }
+
+    /**
+     * Gets a single $table/$field information piece
+     * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
+     *
+     * @param string $table CSH key / table name
+     * @param string $field Sub key / field name
+     * @param bool $anchors If anchors is to be shown.
+     * @return array with the information
+     */
+    protected function getItem($table, $field, $anchors = false)
+    {
+        if (!empty($table)) {
+            $field = !empty($field) ? $field : '';
+            $setup = $GLOBALS['TCA_DESCR'][$table]['columns'][$field];
+            return [
+                'table' => $table,
+                'field' => $field,
+                'configuration' => $setup,
+                'headerLine' => $this->getTableFieldLabel($table, $field),
+                'content' => !empty($setup['description']) ? $setup['description'] : '',
+                'images' => !empty($setup['image']) ? $this->getImages($setup['image'], $setup['image_descr']) : [],
+                'seeAlso' => !empty($setup['seeAlso']) ? $this->getSeeAlsoLinks($setup['seeAlso'], $anchors ? $table : '') : '',
+            ];
+        }
+        return [];
+    }
+
+    /**
+     * Get see-also links
+     *
+     * @param string $value See-also input codes
+     * @param string $anchorTable If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
+     * @return array See-also links
+     */
+    protected function getSeeAlsoLinks($value, $anchorTable = '')
+    {
+        // Split references by comma or linebreak
+        $items = preg_split('/[,' . LF . ']/', $value);
+        $lines = [];
+        foreach ($items as $itemValue) {
+            $itemValue = trim($itemValue);
+            if ($itemValue) {
+                $reference = GeneralUtility::trimExplode(':', $itemValue);
+                $referenceUrl = GeneralUtility::trimExplode('|', $itemValue);
+                if (substr($referenceUrl[1], 0, 4) === 'http') {
+                    // URL reference
+                    $lines[] = [
+                        'url' => $referenceUrl[1],
+                        'title' => $referenceUrl[0],
+                        'target' => '_blank'
+                    ];
+                } elseif (substr($referenceUrl[1], 0, 5) === 'FILE:') {
+                    // File reference
+                    $fileName = GeneralUtility::getFileAbsFileName(substr($referenceUrl[1], 5));
+                    if ($fileName && @is_file($fileName)) {
+                        $fileName = '../' . PathUtility::stripPathSitePrefix($fileName);
+                        $lines[] = [
+                            'url' => $fileName,
+                            'title' => $referenceUrl[0],
+                            'target' => '_blank'
+                        ];
+                    }
+                } else {
+                    // Table reference
+                    $table = !empty($reference[0]) ? $reference[0] : '';
+                    $field = !empty($reference[1]) ? $reference[1] : '';
+                    $accessAllowed = true;
+                    // Check if table exists and current user can access it
+                    if (!empty($table)) {
+                        $accessAllowed = !$this->getTableSetup($table) || $this->checkAccess('tables_select', $table);
+                    }
+                    // Check if field exists and is excludable or user can access it
+                    if ($accessAllowed && !empty($field)) {
+                        $accessAllowed = !$this->isExcludableField($table, $field) || $this->checkAccess('non_exclude_fields', $table . ':' . $field);
+                    }
+                    // Check read access
+                    if ($accessAllowed && isset($GLOBALS['TCA_DESCR'][$table])) {
+                        // Make see-also link
+                        $label = $this->getTableFieldLabel($table, $field, ' / ');
+                        if ($anchorTable && $table === $anchorTable) {
+                            $lines[] = [
+                                'url' => '#' . rawurlencode(implode('.', $reference)),
+                                'title' => $label,
+                            ];
+                        } else {
+                            $lines[] = [
+                                'internal' => true,
+                                'arguments' => [
+                                    'table' => $table,
+                                    'field' => $field
+                                ],
+                                'title' => $label
+                            ];
+                        }
+                    }
+                }
+            }
+        }
+        return $lines;
+    }
+
+    /**
+     * Check if given table / field is excludable
+     *
+     * @param string $table The table
+     * @param string $field The field
+     * @return bool TRUE if given field is excludable
+     */
+    protected function isExcludableField($table, $field)
+    {
+        $fieldSetup = $this->getFieldSetup($table, $field);
+        if (!empty($fieldSetup)) {
+            return !empty($fieldSetup['exclude']);
+        }
+        return false;
+    }
+
+    /**
+     * Returns an array of images with description
+     *
+     * @param string $images Image file reference (list of)
+     * @param string $descriptions Description string (divided for each image by line break)
+     * @return array
+     */
+    protected function getImages($images, $descriptions)
+    {
+        $imageData = [];
+        // Splitting
+        $imgArray = GeneralUtility::trimExplode(',', $images, true);
+        if (!empty($imgArray)) {
+            $descrArray = explode(LF, $descriptions, count($imgArray));
+            foreach ($imgArray as $k => $image) {
+                $descriptions = $descrArray[$k];
+                $absImagePath = GeneralUtility::getFileAbsFileName($image);
+                if ($absImagePath && @is_file($absImagePath)) {
+                    $imgFile = PathUtility::stripPathSitePrefix($absImagePath);
+                    $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $absImagePath);
+                    if ($imageInfo->getWidth()) {
+                        $imageData[] = [
+                            'image' => $imgFile,
+                            'description' => $descriptions
+                        ];
+                    }
+                }
+            }
+        }
+        return $imageData;
+    }
+
+    /**
+     * Returns the setup for given table
+     *
+     * @param string $table The table
+     * @return array The table setup
+     */
+    protected function getTableSetup($table)
+    {
+        if (!empty($table) && !empty($GLOBALS['TCA'][$table])) {
+            return $GLOBALS['TCA'][$table];
+        }
+        return [];
+    }
+
+    /**
+     * Returns the setup for given table / field
+     *
+     * @param string $table The table
+     * @param string $field The field
+     * @param bool $allowEmptyField Allow empty field
+     * @return array The field setup
+     */
+    protected function getFieldSetup($table, $field, $allowEmptyField = false)
+    {
+        $tableSetup = $this->getTableSetup($table);
+        if (!empty($tableSetup) && (!empty($field) || $allowEmptyField) && !empty($tableSetup['columns'][$field])) {
+            return $tableSetup['columns'][$field];
+        }
+        return [];
+    }
+
+    /**
+     * Check if current backend user has access to given identifier
+     *
+     * @param string $type The type
+     * @param string $identifier The search string in access list
+     * @return bool TRUE if the user has access
+     */
+    protected function checkAccess($type, $identifier)
+    {
+        if (!empty($type) && !empty($identifier)) {
+            return $this->getBackendUser()->check($type, $identifier);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the current BE user.
+     *
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser(): BackendUserAuthentication
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return \TYPO3\CMS\Core\Localization\LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+}
index 0d0c1cc..08cf56a 100644 (file)
@@ -16,7 +16,9 @@ namespace TYPO3\CMS\Backend\Template;
 
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
@@ -503,6 +505,17 @@ function jumpToUrl(URL) {
         // this logic will be changed once Twitter bootstrap 4 is included
         $this->pageRenderer->addJsFile('EXT:core/Resources/Public/JavaScript/Contrib/bootstrap/bootstrap.js');
 
+        // csh manual require js module & moduleUrl
+        if (TYPO3_MODE === 'BE' && $this->getBackendUser() && !empty($this->getBackendUser()->user)) {
+            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+            $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
+            $this->pageRenderer->addInlineSetting(
+                'ContextHelp',
+                'moduleUrl',
+                (string)$uriBuilder->buildUriFromRoute('help_cshmanual', ['action' => 'detail'])
+            );
+        }
+
         // hook for additional headerData
         foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'] ?? [] as $hookFunction) {
             $hookParameters = [
@@ -967,4 +980,12 @@ function jumpToUrl(URL) {
         }
         return $urlPrefix . $filename;
     }
+
+    /**
+     * @return BackendUserAuthentication|null
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'] ?? null;
+    }
 }
index ffa93e5..b6b8ad6 100644 (file)
@@ -2470,13 +2470,9 @@ class BackendUtility
             $helpText = self::helpText($table, $field);
         }
         // If there's a help text or some overload information, proceed with preparing an output
-        // @todo: right now this is a hard dependency on csh manual, as the whole help system should be moved to
-        // the extension. The core provides an API for adding help and rendering help, but the rendering
-        // should be up to the extension itself
-        if ((!empty($helpText) || $hasHelpTextOverload) && ExtensionManagementUtility::isLoaded('documentation')) {
+        if ((!empty($helpText) || $hasHelpTextOverload)) {
             // If no text was given, just use the regular help icon
             if ($text == '') {
-                /** @var IconFactory $iconFactory */
                 $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
                 $text = $iconFactory->getIcon('actions-system-help-open', Icon::SIZE_SMALL)->render();
                 $abbrClassAdd = '-icon';
index 81b11a5..3e74095 100644 (file)
@@ -2,4 +2,5 @@
 return [
     'TYPO3\\CMS\\Backend\\AjaxLoginHandler' => \TYPO3\CMS\Backend\Controller\AjaxLoginController::class,
     'TYPO3\\CMS\\Backend\\Form\\Wizard\\ImageManipulationWizard' => \TYPO3\CMS\Backend\Controller\Wizard\ImageManipulationController::class,
+    'TYPO3\\CMS\\Cshmanual\\Domain\\Repository\\TableManualRepository' => \TYPO3\CMS\Backend\Domain\Repository\TableManualRepository::class,
 ];
index d19be3d..da71047 100644 (file)
@@ -20,3 +20,12 @@ namespace TYPO3\CMS\Backend\Form\Wizard {
     {
     }
 }
+
+namespace TYPO3\CMS\Cshmanual\Domain\Repository {
+    /**
+     * @deprecated since v9, will be removed in v10
+     */
+    class TableManualRepository extends \TYPO3\CMS\Backend\Domain\Repository\TableManualRepository
+    {
+    }
+}
diff --git a/typo3/sysext/backend/Resources/Private/Language/locallang_mod_help_cshmanual.xlf b/typo3/sysext/backend/Resources/Private/Language/locallang_mod_help_cshmanual.xlf
new file mode 100644 (file)
index 0000000..eea936d
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
+       <file t3:id="1415814872" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:34Z" product-name="lang">
+               <header/>
+               <body>
+                       <trans-unit id="mlang_labels_tablabel">
+                               <source>TYPO3 Inline Manual</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_labels_tabdescr">
+                               <source>Inline Manual based on the information sources for Context Sensitive Help in the system.</source>
+                       </trans-unit>
+                       <trans-unit id="mlang_tabs_tab">
+                               <source>TYPO3 Manual</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
diff --git a/typo3/sysext/backend/Resources/Private/Language/locallang_view_help.xlf b/typo3/sysext/backend/Resources/Private/Language/locallang_view_help.xlf
new file mode 100644 (file)
index 0000000..61bbd5e
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
+       <file t3:id="1415814889" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:34Z" product-name="lang">
+               <header/>
+               <body>
+                       <trans-unit id="details">
+                               <source>Details</source>
+                       </trans-unit>
+                       <trans-unit id="syntax">
+                               <source>Syntax</source>
+                       </trans-unit>
+                       <trans-unit id="seeAlso">
+                               <source>See also</source>
+                       </trans-unit>
+                       <trans-unit id="goBack">
+                               <source>Go back</source>
+                       </trans-unit>
+                       <trans-unit id="fullDescription">
+                               <source>See full description of table</source>
+                       </trans-unit>
+                       <trans-unit id="fullDescription_module">
+                               <source>See full description of module</source>
+                       </trans-unit>
+                       <trans-unit id="goToToc">
+                               <source>&lt;&lt; go to Manual Index</source>
+                       </trans-unit>
+                       <trans-unit id="to_top">
+                               <source>To top</source>
+                       </trans-unit>
+                       <trans-unit id="TOC">
+                               <source>Table Of Contents</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_core">
+                               <source>TYPO3 Core Features</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_modules">
+                               <source>Backend Modules</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_tables">
+                               <source>Database Tables</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_extensions">
+                               <source>Extensions</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_glossary">
+                               <source>Glossary</source>
+                       </trans-unit>
+                       <trans-unit id="TOC_other">
+                               <source>Other</source>
+                       </trans-unit>
+                       <trans-unit id="close">
+                               <source>Close</source>
+                       </trans-unit>
+                       <trans-unit id="title">
+                               <source>TYPO3 Inline Help</source>
+                       </trans-unit>
+                       <trans-unit id="manual_title">
+                               <source>TYPO3 Inline User Manual</source>
+                       </trans-unit>
+                       <trans-unit id="introduction">
+                               <source>Introduction</source>
+                       </trans-unit>
+                       <trans-unit id="description">
+                               <source>The TYPO3 Inline User Manual is composed from the available help in this TYPO3 Installation (Context Sensitive Help). Here you will find a general description of the TYPO3 Core modules, installation specific Backend Modules and Database Tables that are available based on your login credentials.</source>
+                       </trans-unit>
+                       <trans-unit id="full_manual">
+                               <source>Full Manual (in one page)</source>
+                       </trans-unit>
+                       <trans-unit id="full_manual_chapters">
+                               <source>Manual Chapters</source>
+                       </trans-unit>
+               </body>
+       </file>
+</xliff>
diff --git a/typo3/sysext/backend/Resources/Private/Layouts/ContextSensitiveHelp.html b/typo3/sysext/backend/Resources/Private/Layouts/ContextSensitiveHelp.html
new file mode 100644 (file)
index 0000000..2738dec
--- /dev/null
@@ -0,0 +1,11 @@
+<div class="tx_cshmanual">
+       <f:render section="content" />
+
+       <hr />
+       <div class="t3-copyright-notice">
+
+               <p>
+                       <f:format.raw>{copyright}</f:format.raw>
+               </p>
+       </div>
+</div>
diff --git a/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html b/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/Manual.html
new file mode 100644 (file)
index 0000000..01dd2e1
--- /dev/null
@@ -0,0 +1,52 @@
+<a id="{manual.table}{f:if(condition:manual.field,then:'.{manual.field}')}"></a>
+
+<h2>{manual.headerLine}</h2>
+
+<p>{manual.content -> 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>
+       {manual.configuration.details -> f:format.stripTags(allowedTags:'<strong><em><b><i>') -> f:format.nl2br()}
+</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>
+
+                       </li>
+               </f:for>
+       </ul>
+</f:if>
diff --git a/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/TableOfContents.html b/typo3/sysext/backend/Resources/Private/Partials/ContextSensitiveHelp/TableOfContents.html
new file mode 100644 (file)
index 0000000..f1daf79
--- /dev/null
@@ -0,0 +1,41 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+
+<h1>
+       <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:manual_title" />
+</h1>
+<p class="lead">
+       <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:description" />
+</p>
+
+<h2>
+       <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:TOC" />
+</h2>
+
+<f:if condition="{toc}">
+       <ul>
+               <f:for each="{toc}" as="modules" key="type">
+                       <li>
+                               <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:TOC_{type}" default="{type}" />
+
+                               <ul>
+                                       <f:for each="{modules}" as="title" key="module">
+                                               <li>
+                                                       <f:if condition="{all}">
+                                                               <f:then>
+                                                                       <a href="#{module}">{module}</a>
+                                                               </f:then>
+                                                               <f:else>
+                                                                       <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'detail', table:module,field:'*'})}">
+                                                                               {title}
+                                                                       </a>
+                                                               </f:else>
+                                                       </f:if>
+                                               </li>
+                                       </f:for>
+                               </ul>
+                       </li>
+               </f:for>
+       </ul>
+</f:if>
+
+</html>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/All.html b/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/All.html
new file mode 100644 (file)
index 0000000..40eaa9b
--- /dev/null
@@ -0,0 +1,11 @@
+<f:layout name="ContextSensitiveHelp" />
+
+<f:section name="content">
+       <f:render partial="ContextSensitiveHelp/TableOfContents" arguments="{toc:all.toc, all:1}" />
+
+       <f:for each="{all.content}" as="sections">
+               <f:for each="{sections.content}" as="item">
+                       <f:render partial="ContextSensitiveHelp/Manual" arguments="{manual:item}" />
+               </f:for>
+       </f:for>
+</f:section>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Detail.html b/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Detail.html
new file mode 100644 (file)
index 0000000..001aa81
--- /dev/null
@@ -0,0 +1,7 @@
+<f:layout name="ContextSensitiveHelp" />
+
+<f:section name="content">
+       <f:for each="{manuals}" as="manual">
+               <f:render partial="ContextSensitiveHelp/Manual" arguments="{manual:manual}" />
+       </f:for>
+</f:section>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Index.html b/typo3/sysext/backend/Resources/Private/Templates/ContextSensitiveHelp/Index.html
new file mode 100644 (file)
index 0000000..a3e439e
--- /dev/null
@@ -0,0 +1,15 @@
+<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
+
+<f:layout name="ContextSensitiveHelp" />
+
+<f:section name="docheader">
+
+</f:section>
+<f:section name="content">
+       <f:render partial="ContextSensitiveHelp/TableOfContents" arguments="{toc:toc,all:0}" />
+
+       <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'all'})}">
+               <f:translate key="LLL:EXT:backend/Resources/Private/Language/locallang_view_help.xlf:full_manual" />
+       </a>
+</f:section>
+</html>
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Public/Icons/module-cshmanual.svg b/typo3/sysext/backend/Resources/Public/Icons/module-cshmanual.svg
new file mode 100644 (file)
index 0000000..6a5246a
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill="#E49139" d="M0 0h64v64H0z"/><path fill="#FFF" d="M45 50H19c-.6 0-1-.4-1-1V15c0-.6.4-1 1-1h26c.6 0 1 .4 1 1v34c0 .6-.4 1-1 1z"/><path fill="#E49139" d="M20 16h2v32h-2zM26 18h16v2H26z"/></svg>
\ No newline at end of file
index b647654..67601cb 100644 (file)
@@ -21,6 +21,7 @@
        "replace": {
                "backend": "*",
                "typo3/cms-context-help": "*",
+               "typo3/cms-cshmanual": "*",
                "typo3/cms-func-wizards": "*",
                "typo3/cms-wizard-crpages": "*",
                "typo3/cms-wizard-sortpages": "*"
index ac86abf..387d486 100644 (file)
@@ -47,3 +47,18 @@ $GLOBALS['TBE_STYLES']['skins']['backend'] = [
     'pages_new',
     'EXT:backend/Resources/Private/Language/locallang_pages_new_csh.xlf'
 );
+
+// Csh manual
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule(
+    'help',
+    'cshmanual',
+    'top',
+    '',
+    [
+        'routeTarget' => \TYPO3\CMS\Backend\Controller\HelpController::class . '::handleRequest',
+        'name' => 'help_cshmanual',
+        'access' => 'user,group',
+        'icon' => 'EXT:backend/Resources/Public/Icons/module-cshmanual.svg',
+        'labels' => 'LLL:EXT:backend/Resources/Private/Language/locallang_mod_help_cshmanual.xlf',
+    ]
+);
diff --git a/typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoBackend.rst b/typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoBackend.rst
new file mode 100644 (file)
index 0000000..169c2f3
--- /dev/null
@@ -0,0 +1,17 @@
+.. include:: ../../Includes.txt
+
+=========================================================
+Important: #81574 - Merged EXT:cshmanual into EXT:backend
+=========================================================
+
+See :issue:`81574`
+
+Description
+===========
+
+The system extension `cshmanual` was migrated into the "backend" extension.
+
+The functionality goes in line with streamline the amount of system extensions and
+sorting out parts which belong together conceptually.
+
+.. index:: Backend
diff --git a/typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst b/typo3/sysext/core/Documentation/Changelog/9.0/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst
deleted file mode 100644 (file)
index a00fd74..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-.. include:: ../../Includes.txt
-
-===============================================================
-Important: #81574 - Merged EXT:cshmanual into EXT:documentation
-===============================================================
-
-See :issue:`81574`
-
-Description
-===========
-
-The system extension `cshmanual` was migrated into the "documentation" extension.
-
-The functionality goes in line with streamline the amount of system extensions and
-sorting out parts which belong together conceptually.
-
-.. index:: Backend, ext:documentation
diff --git a/typo3/sysext/documentation/Classes/Controller/HelpController.php b/typo3/sysext/documentation/Classes/Controller/HelpController.php
deleted file mode 100644 (file)
index 0ca9521..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-<?php
-declare(strict_types = 1);
-namespace TYPO3\CMS\Documentation\Controller;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Backend\Template\ModuleTemplate;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Http\HtmlResponse;
-use TYPO3\CMS\Core\Http\RedirectResponse;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Localization\LanguageService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Documentation\Domain\Repository\TableManualRepository;
-use TYPO3\CMS\Fluid\View\StandaloneView;
-use TYPO3Fluid\Fluid\View\ViewInterface;
-
-/**
- * Main help module controller
- */
-class HelpController
-{
-    /**
-     * Section identifiers
-     */
-    const FULL = 0;
-
-    /**
-     * Show only Table of contents
-     */
-    const TOC_ONLY = 1;
-
-    /**
-     * @var TableManualRepository
-     */
-    protected $tableManualRepository;
-
-    /** @var ModuleTemplate */
-    protected $moduleTemplate;
-
-    /** @var ViewInterface */
-    protected $view;
-
-    /**
-     * Instantiate the report controller
-     */
-    public function __construct()
-    {
-        $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
-        $this->tableManualRepository = GeneralUtility::makeInstance(TableManualRepository::class);
-    }
-
-    /**
-     * Injects the request object for the current request, and renders correct action
-     *
-     * @param ServerRequestInterface $request the current request
-     * @return ResponseInterface the response with the content
-     */
-    public function handleRequest(ServerRequestInterface $request): ResponseInterface
-    {
-        $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'index';
-
-        if ($action === 'detail') {
-            $table = $request->getQueryParams()['table'] ?? $request->getParsedBody()['table'];
-            if (!$table) {
-                $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-                return new RedirectResponse((string)$uriBuilder->buildUriFromRoute('help_cshmanual', [
-                    'action' => 'index',
-                ]), 303);
-            }
-        }
-
-        $this->initializeView($action);
-
-        $result = call_user_func_array([$this, $action . 'Action'], [$request]);
-        if ($result instanceof ResponseInterface) {
-            return $result;
-        }
-
-        $this->registerDocheaderButtons($request);
-
-        $this->moduleTemplate->setContent($this->view->render());
-        return new HtmlResponse($this->moduleTemplate->renderContent());
-    }
-
-    /**
-     * @param string $templateName
-     */
-    protected function initializeView(string $templateName)
-    {
-        $this->view = GeneralUtility::makeInstance(StandaloneView::class);
-        $this->view->setTemplate($templateName);
-        $this->view->setTemplateRootPaths(['EXT:documentation/Resources/Private/Templates/Help']);
-        $this->view->setPartialRootPaths(['EXT:documentation/Resources/Private/Partials']);
-        $this->view->setLayoutRootPaths(['EXT:documentation/Resources/Private/Layouts']);
-        $this->view->getRequest()->setControllerExtensionName('Documentation');
-        $this->view->assign('copyright', BackendUtility::TYPO3_copyRightNotice());
-    }
-
-    /**
-     * Show table of contents
-     */
-    public function indexAction()
-    {
-        $this->view->assign('toc', $this->tableManualRepository->getSections(self::TOC_ONLY));
-    }
-
-    /**
-     * Show the table of contents and all manuals
-     */
-    public function allAction()
-    {
-        $this->view->assign('all', $this->tableManualRepository->getSections(self::FULL));
-    }
-
-    /**
-     * Show a single manual
-     *
-     * @param ServerRequestInterface $request
-     */
-    public function detailAction(ServerRequestInterface $request)
-    {
-        $table = $request->getQueryParams()['table'] ?? $request->getParsedBody()['table'];
-        $field = $request->getQueryParams()['field'] ?? $request->getParsedBody()['field'] ?? '*';
-
-        $mainKey = $table;
-        $identifierParts = GeneralUtility::trimExplode('.', $field);
-        // The field is the second one
-        if (count($identifierParts) > 1) {
-            array_shift($field);
-            // There's at least one extra part
-            $extraIdentifierInformation = [];
-            $extraIdentifierInformation[] = array_shift($identifierParts);
-            // If the ds_pointerField contains a comma, it means the choice of FlexForm DS
-            // is determined by 2 parameters. In this case we have an extra identifier part
-            if (strpos($GLOBALS['TCA'][$table]['columns'][$field]['config']['ds_pointerField'], ',') !== false) {
-                $extraIdentifierInformation[] = array_shift($identifierParts);
-            }
-            // The remaining parts make up the FlexForm field name itself (reassembled with dots)
-            $flexFormField = implode('.', $identifierParts);
-            // Assemble a different main key and switch field to use FlexForm field name
-            $mainKey .= '.' . $field;
-            foreach ($extraIdentifierInformation as $extraKey) {
-                $mainKey .= '.' . $extraKey;
-            }
-            $field = $flexFormField;
-        }
-
-        $this->view->assignMultiple([
-            'table' => $table,
-            'key' => $mainKey,
-            'field' => $field,
-            'manuals' => $field === '*' ? $this->tableManualRepository->getTableManual($mainKey) : [$this->tableManualRepository->getSingleManual($mainKey, $field)],
-        ]);
-    }
-
-    /**
-     * Registers the Icons into the docheader
-     *
-     * @param ServerRequestInterface $request
-     */
-    protected function registerDocheaderButtons(ServerRequestInterface $request)
-    {
-        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
-
-        if ($this->getBackendUser()->mayMakeShortcut()) {
-            $shortcutButton = $buttonBar->makeShortcutButton()
-                ->setModuleName('help_cshmanual')
-                ->setGetVariables(['table', 'field', 'route']);
-            $buttonBar->addButton($shortcutButton);
-        }
-
-        $action = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'] ?? 'index';
-        if ($action !== 'index') {
-            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-            $backButton = $buttonBar->makeLinkButton()
-                ->setTitle($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:back'))
-                ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL))
-                ->setHref((string)$uriBuilder->buildUriFromRoute('help_cshmanual'));
-            $buttonBar->addButton($backButton);
-        }
-    }
-
-    /**
-     * Returns the currently logged in BE user
-     *
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser(): BackendUserAuthentication
-    {
-        return $GLOBALS['BE_USER'];
-    }
-
-    /**
-     * Returns the LanguageService
-     *
-     * @return LanguageService
-     */
-    protected function getLanguageService(): LanguageService
-    {
-        return $GLOBALS['LANG'];
-    }
-}
diff --git a/typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php b/typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php
deleted file mode 100644 (file)
index 93c3a66..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-<?php
-namespace TYPO3\CMS\Documentation\Domain\Repository;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Type\File\ImageInfo;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\PathUtility;
-
-/**
- * Table manual repository
- */
-class TableManualRepository
-{
-    /**
-     * @var \TYPO3\CMS\Documentation\Service\AccessService
-     */
-    protected $accessService;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->accessService = GeneralUtility::makeInstance(\TYPO3\CMS\Documentation\Service\AccessService::class);
-    }
-
-    /**
-     * Get the manual of the given table
-     *
-     * @param string $table
-     * @return array the manual for a TCA table, see getItem() for details
-     */
-    public function getTableManual($table)
-    {
-        $parts = [];
-
-        // Load descriptions for table $table
-        $this->getLanguageService()->loadSingleTableDescription($table);
-        if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $this->accessService->checkAccess('tables_select', $table)) {
-            // Reserved for header of table
-            $parts[0] = '';
-            // Traverse table columns as listed in TCA_DESCR
-            foreach ($GLOBALS['TCA_DESCR'][$table]['columns'] as $field => $_) {
-                if (!$this->isExcludableField($table, $field) || $this->accessService->checkAccess('non_exclude_fields', $table . ':' . $field)) {
-                    if (!$field) {
-                        // Header
-                        $parts[0] = $this->getItem($table, '', true);
-                    } else {
-                        // Field
-                        $parts[] = $this->getItem($table, $field, true);
-                    }
-                }
-            }
-            if (!$parts[0]) {
-                unset($parts[0]);
-            }
-        }
-        return $parts;
-    }
-
-    /**
-     * Get a single manual
-     *
-     * @param string $table table name
-     * @param string $field field name
-     * @return array
-     */
-    public function getSingleManual($table, $field)
-    {
-        $this->getLanguageService()->loadSingleTableDescription($table);
-        return $this->getItem($table, $field);
-    }
-
-    /**
-     * Get TOC sections
-     *
-     * @param string $mode
-     * @return array
-     */
-    public function getSections($mode)
-    {
-        // Initialize
-        $cshKeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
-        $tcaKeys = array_keys($GLOBALS['TCA']);
-        $outputSections = [];
-        $tocArray = [];
-        // TYPO3 Core Features
-        $lang = $this->getLanguageService();
-        $lang->loadSingleTableDescription('xMOD_csh_corebe');
-        $this->renderTableOfContentItem($mode, 'xMOD_csh_corebe', 'core', $outputSections, $tocArray, $cshKeys);
-        // Backend Modules
-        $loadModules = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
-        $loadModules->load($GLOBALS['TBE_MODULES']);
-        foreach ($loadModules->modules as $mainMod => $info) {
-            $cshKey = '_MOD_' . $mainMod;
-            if ($cshKeys[$cshKey]) {
-                $lang->loadSingleTableDescription($cshKey);
-                $this->renderTableOfContentItem($mode, $cshKey, 'modules', $outputSections, $tocArray, $cshKeys);
-            }
-            if (is_array($info['sub'])) {
-                foreach ($info['sub'] as $subMod => $subInfo) {
-                    $cshKey = '_MOD_' . $mainMod . '_' . $subMod;
-                    if ($cshKeys[$cshKey]) {
-                        $lang->loadSingleTableDescription($cshKey);
-                        $this->renderTableOfContentItem($mode, $cshKey, 'modules', $outputSections, $tocArray, $cshKeys);
-                    }
-                }
-            }
-        }
-        // Database Tables
-        foreach ($tcaKeys as $table) {
-            // Load descriptions for table $table
-            $lang->loadSingleTableDescription($table);
-            if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $this->accessService->checkAccess('tables_select', $table)) {
-                $this->renderTableOfContentItem($mode, $table, 'tables', $outputSections, $tocArray, $cshKeys);
-            }
-        }
-        foreach ($cshKeys as $cshKey => $value) {
-            // Extensions
-            if (GeneralUtility::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($GLOBALS['TCA'][$cshKey])) {
-                $lang->loadSingleTableDescription($cshKey);
-                $this->renderTableOfContentItem($mode, $cshKey, 'extensions', $outputSections, $tocArray, $cshKeys);
-            }
-            // Other
-            if (!GeneralUtility::isFirstPartOfStr($cshKey, '_MOD_') && !isset($GLOBALS['TCA'][$cshKey])) {
-                $lang->loadSingleTableDescription($cshKey);
-                $this->renderTableOfContentItem($mode, $cshKey, 'other', $outputSections, $tocArray, $cshKeys);
-            }
-        }
-
-        if ($mode === \TYPO3\CMS\Documentation\Controller\HelpController::TOC_ONLY) {
-            return $tocArray;
-        }
-
-        return [
-            'toc' => $tocArray,
-            'content' => $outputSections
-        ];
-    }
-
-    /**
-     * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
-     *
-     * @param int $mode Mode
-     * @param string $table CSH key / Table name
-     * @param string $tocCat TOC category keyword: "core", "modules", "tables", "other
-     * @param array $outputSections Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
-     * @param array $tocArray TOC array; Here TOC index elements are created. Passed by reference!
-     * @param array $CSHkeys CSH keys array. Every item rendered will be unset in this array so finally we can see what CSH keys are not processed yet. Passed by reference!
-     */
-    protected function renderTableOfContentItem($mode, $table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys)
-    {
-        $tocArray[$tocCat][$table] = $this->getTableFieldLabel($table);
-        if (!$mode) {
-            // Render full manual right here!
-            $outputSections[$table]['content'] = $this->getTableManual($table);
-            if (!$outputSections[$table]) {
-                unset($outputSections[$table]);
-            }
-        }
-
-        // Unset CSH key
-        unset($CSHkeys[$table]);
-    }
-
-    /**
-     * Returns composite label for table/field
-     *
-     * @param string $key CSH key / table name
-     * @param string $field Sub key / field name
-     * @param string $mergeToken Token to merge the two strings with
-     * @return string Labels joined with merge token
-     * @see getTableFieldNames()
-     */
-    protected function getTableFieldLabel($key, $field = '', $mergeToken = ': ')
-    {
-        // Get table / field parts
-        list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
-        // Create label
-        return $this->getLanguageService()->sL($tableName) . ($field ? $mergeToken . rtrim(trim($this->getLanguageService()->sL($fieldName)), ':') : '');
-    }
-
-    /**
-     * Returns labels for a given field in a given structure
-     *
-     * @param string $key CSH key / table name
-     * @param string $field Sub key / field name
-     * @return array Table and field labels in a numeric array
-     */
-    protected function getTableFieldNames($key, $field)
-    {
-        $this->getLanguageService()->loadSingleTableDescription($key);
-        // Define the label for the key
-        if (!empty($GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'])) {
-            // If there's an alternative title, use it
-            $keyName = $GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'];
-        } elseif (isset($GLOBALS['TCA'][$key])) {
-            // Otherwise, if it's a table, use its title
-            $keyName = $GLOBALS['TCA'][$key]['ctrl']['title'];
-        } else {
-            // If no title was found, make sure to remove any "_MOD_"
-            $keyName = preg_replace('/^_MOD_/', '', $key);
-        }
-        // Define the label for the field
-        $fieldName = $field;
-        if (!empty($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'])) {
-            // If there's an alternative title, use it
-            $fieldName = $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'];
-        } elseif (!empty($GLOBALS['TCA'][$key]['columns'][$field])) {
-            // Otherwise, if it's a table, use its title
-            $fieldName = $GLOBALS['TCA'][$key]['columns'][$field]['label'];
-        }
-        return [$keyName, $fieldName];
-    }
-
-    /**
-     * Gets a single $table/$field information piece
-     * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
-     *
-     * @param string $table CSH key / table name
-     * @param string $field Sub key / field name
-     * @param bool $anchors If anchors is to be shown.
-     * @return array with the information
-     */
-    protected function getItem($table, $field, $anchors = false)
-    {
-        if (!empty($table)) {
-            $field = !empty($field) ? $field : '';
-            $setup = $GLOBALS['TCA_DESCR'][$table]['columns'][$field];
-            return [
-                'table' => $table,
-                'field' => $field,
-                'configuration' => $setup,
-                'headerLine' => $this->getTableFieldLabel($table, $field),
-                'content' => !empty($setup['description']) ? $setup['description'] : '',
-                'images' => !empty($setup['image']) ? $this->getImages($setup['image'], $setup['image_descr']) : [],
-                'seeAlso' => !empty($setup['seeAlso']) ? $this->getSeeAlsoLinks($setup['seeAlso'], $anchors ? $table : '') : '',
-            ];
-        }
-        return [];
-    }
-
-    /**
-     * Get see-also links
-     *
-     * @param string $value See-also input codes
-     * @param string $anchorTable If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
-     * @return array See-also links
-     */
-    protected function getSeeAlsoLinks($value, $anchorTable = '')
-    {
-        // Split references by comma or linebreak
-        $items = preg_split('/[,' . LF . ']/', $value);
-        $lines = [];
-        foreach ($items as $itemValue) {
-            $itemValue = trim($itemValue);
-            if ($itemValue) {
-                $reference = GeneralUtility::trimExplode(':', $itemValue);
-                $referenceUrl = GeneralUtility::trimExplode('|', $itemValue);
-                if (substr($referenceUrl[1], 0, 4) === 'http') {
-                    // URL reference
-                    $lines[] = [
-                        'url' => $referenceUrl[1],
-                        'title' => $referenceUrl[0],
-                        'target' => '_blank'
-                    ];
-                } elseif (substr($referenceUrl[1], 0, 5) === 'FILE:') {
-                    // File reference
-                    $fileName = GeneralUtility::getFileAbsFileName(substr($referenceUrl[1], 5));
-                    if ($fileName && @is_file($fileName)) {
-                        $fileName = '../' . PathUtility::stripPathSitePrefix($fileName);
-                        $lines[] = [
-                            'url' => $fileName,
-                            'title' => $referenceUrl[0],
-                            'target' => '_blank'
-                        ];
-                    }
-                } else {
-                    // Table reference
-                    $table = !empty($reference[0]) ? $reference[0] : '';
-                    $field = !empty($reference[1]) ? $reference[1] : '';
-                    $accessAllowed = true;
-                    // Check if table exists and current user can access it
-                    if (!empty($table)) {
-                        $accessAllowed = !$this->getTableSetup($table) || $this->accessService->checkAccess('tables_select', $table);
-                    }
-                    // Check if field exists and is excludable or user can access it
-                    if ($accessAllowed && !empty($field)) {
-                        $accessAllowed = !$this->isExcludableField($table, $field) || $this->accessService->checkAccess('non_exclude_fields', $table . ':' . $field);
-                    }
-                    // Check read access
-                    if ($accessAllowed && isset($GLOBALS['TCA_DESCR'][$table])) {
-                        // Make see-also link
-                        $label = $this->getTableFieldLabel($table, $field, ' / ');
-                        if ($anchorTable && $table === $anchorTable) {
-                            $lines[] = [
-                                'url' => '#' . rawurlencode(implode('.', $reference)),
-                                'title' => $label,
-                            ];
-                        } else {
-                            $lines[] = [
-                                'internal' => true,
-                                'arguments' => [
-                                    'table' => $table,
-                                    'field' => $field
-                                ],
-                                'title' => $label
-                            ];
-                        }
-                    }
-                }
-            }
-        }
-        return $lines;
-    }
-
-    /**
-     * Check if given table / field is excludable
-     *
-     * @param string $table The table
-     * @param string $field The field
-     * @return bool TRUE if given field is excludable
-     */
-    protected function isExcludableField($table, $field)
-    {
-        $fieldSetup = $this->getFieldSetup($table, $field);
-        if (!empty($fieldSetup)) {
-            return !empty($fieldSetup['exclude']);
-        }
-        return false;
-    }
-
-    /**
-     * Returns an array of images with description
-     *
-     * @param string $images Image file reference (list of)
-     * @param string $descriptions Description string (divided for each image by line break)
-     * @return array
-     */
-    protected function getImages($images, $descriptions)
-    {
-        $imageData = [];
-        // Splitting
-        $imgArray = GeneralUtility::trimExplode(',', $images, true);
-        if (!empty($imgArray)) {
-            $descrArray = explode(LF, $descriptions, count($imgArray));
-            foreach ($imgArray as $k => $image) {
-                $descriptions = $descrArray[$k];
-                $absImagePath = GeneralUtility::getFileAbsFileName($image);
-                if ($absImagePath && @is_file($absImagePath)) {
-                    $imgFile = PathUtility::stripPathSitePrefix($absImagePath);
-                    $imageInfo = GeneralUtility::makeInstance(ImageInfo::class, $absImagePath);
-                    if ($imageInfo->getWidth()) {
-                        $imageData[] = [
-                            'image' => $imgFile,
-                            'description' => $descriptions
-                        ];
-                    }
-                }
-            }
-        }
-        return $imageData;
-    }
-
-    /**
-     * Returns the setup for given table
-     *
-     * @param string $table The table
-     * @return array The table setup
-     */
-    protected function getTableSetup($table)
-    {
-        if (!empty($table) && !empty($GLOBALS['TCA'][$table])) {
-            return $GLOBALS['TCA'][$table];
-        }
-        return [];
-    }
-
-    /**
-     * Returns the setup for given table / field
-     *
-     * @param string $table The table
-     * @param string $field The field
-     * @param bool $allowEmptyField Allow empty field
-     * @return array The field setup
-     */
-    protected function getFieldSetup($table, $field, $allowEmptyField = false)
-    {
-        $tableSetup = $this->getTableSetup($table);
-        if (!empty($tableSetup) && (!empty($field) || $allowEmptyField) && !empty($tableSetup['columns'][$field])) {
-            return $tableSetup['columns'][$field];
-        }
-        return [];
-    }
-
-    /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Core\Localization\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-}
diff --git a/typo3/sysext/documentation/Classes/Service/AccessService.php b/typo3/sysext/documentation/Classes/Service/AccessService.php
deleted file mode 100644 (file)
index 7d83205..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-namespace TYPO3\CMS\Documentation\Service;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Access service
- */
-class AccessService
-{
-    /**
-     * Check if current backend user has access to given identifier
-     *
-     * @param string $type The type
-     * @param string $identifier The search string in access list
-     * @return bool TRUE if the user has access
-     */
-    public function checkAccess($type, $identifier)
-    {
-        if (!empty($type) && !empty($identifier)) {
-            return $this->getBackendUser()->check($type, $identifier);
-        }
-        return false;
-    }
-
-    /**
-     * Returns the current BE user.
-     *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-}
diff --git a/typo3/sysext/documentation/Classes/Service/JavaScriptService.php b/typo3/sysext/documentation/Classes/Service/JavaScriptService.php
deleted file mode 100644 (file)
index ee3e7a0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-namespace TYPO3\CMS\Documentation\Service;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Page\PageRenderer;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * JavaScript Service adding JS code to each backend page
- */
-class JavaScriptService
-{
-    /**
-     * Include the JS for the Context Sensitive Help
-     *
-     * @param string $title the title of the page
-     * @param \TYPO3\CMS\Backend\Template\DocumentTemplate $documentTemplateObject
-     */
-    public function addJavaScript($title, $documentTemplateObject)
-    {
-        if (TYPO3_MODE !== 'BE') {
-            return;
-        }
-        $beUser = $this->getBeUser();
-        if ($beUser && !empty($beUser->user)) {
-            /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */
-            $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
-            $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
-            $pageRenderer->addInlineSetting('ContextHelp', 'moduleUrl', (string)$uriBuilder->buildUriFromRoute('help_cshmanual', [
-                'action' => 'detail'
-            ]));
-        }
-    }
-
-    /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBeUser()
-    {
-        return $GLOBALS['BE_USER'] ?? null;
-    }
-}
diff --git a/typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php b/typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php
deleted file mode 100644 (file)
index e4960e9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-return [
-    'TYPO3\\CMS\\Cshmanual\\Domain\\Repository\\TableManualRepository' => \TYPO3\CMS\Documentation\Domain\Repository\TableManualRepository::class,
-    'TYPO3\\CMS\\Cshmanual\\Service\\AccessService' => \TYPO3\CMS\Documentation\Service\AccessService::class,
-    'TYPO3\\CMS\\Cshmanual\\Service\\JavaScriptService' => \TYPO3\CMS\Documentation\Service\JavaScriptService::class
-];
diff --git a/typo3/sysext/documentation/Migrations/Code/LegacyClassesForIde.php b/typo3/sysext/documentation/Migrations/Code/LegacyClassesForIde.php
deleted file mode 100644 (file)
index d4b2b7f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-namespace {
-    die('Access denied');
-}
-
-namespace TYPO3\CMS\Cshmanual\Domain\Repository {
-    class TableManualRepository extends \TYPO3\CMS\Documentation\Domain\Repository\TableManualRepository
-    {
-    }
-}
-
-namespace TYPO3\CMS\Cshmanual\Service {
-    class AccessService extends \TYPO3\CMS\Documentation\Service\AccessService
-    {
-    }
-}
-
-namespace TYPO3\CMS\Cshmanual\Service {
-    class JavaScriptService extends \TYPO3\CMS\Documentation\Service\JavaScriptService
-    {
-    }
-}
diff --git a/typo3/sysext/documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf b/typo3/sysext/documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf
deleted file mode 100644 (file)
index eea936d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
-       <file t3:id="1415814872" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:34Z" product-name="lang">
-               <header/>
-               <body>
-                       <trans-unit id="mlang_labels_tablabel">
-                               <source>TYPO3 Inline Manual</source>
-                       </trans-unit>
-                       <trans-unit id="mlang_labels_tabdescr">
-                               <source>Inline Manual based on the information sources for Context Sensitive Help in the system.</source>
-                       </trans-unit>
-                       <trans-unit id="mlang_tabs_tab">
-                               <source>TYPO3 Manual</source>
-                       </trans-unit>
-               </body>
-       </file>
-</xliff>
diff --git a/typo3/sysext/documentation/Resources/Private/Language/locallang_view_help.xlf b/typo3/sysext/documentation/Resources/Private/Language/locallang_view_help.xlf
deleted file mode 100644 (file)
index 61bbd5e..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff">
-       <file t3:id="1415814889" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:34Z" product-name="lang">
-               <header/>
-               <body>
-                       <trans-unit id="details">
-                               <source>Details</source>
-                       </trans-unit>
-                       <trans-unit id="syntax">
-                               <source>Syntax</source>
-                       </trans-unit>
-                       <trans-unit id="seeAlso">
-                               <source>See also</source>
-                       </trans-unit>
-                       <trans-unit id="goBack">
-                               <source>Go back</source>
-                       </trans-unit>
-                       <trans-unit id="fullDescription">
-                               <source>See full description of table</source>
-                       </trans-unit>
-                       <trans-unit id="fullDescription_module">
-                               <source>See full description of module</source>
-                       </trans-unit>
-                       <trans-unit id="goToToc">
-                               <source>&lt;&lt; go to Manual Index</source>
-                       </trans-unit>
-                       <trans-unit id="to_top">
-                               <source>To top</source>
-                       </trans-unit>
-                       <trans-unit id="TOC">
-                               <source>Table Of Contents</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_core">
-                               <source>TYPO3 Core Features</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_modules">
-                               <source>Backend Modules</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_tables">
-                               <source>Database Tables</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_extensions">
-                               <source>Extensions</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_glossary">
-                               <source>Glossary</source>
-                       </trans-unit>
-                       <trans-unit id="TOC_other">
-                               <source>Other</source>
-                       </trans-unit>
-                       <trans-unit id="close">
-                               <source>Close</source>
-                       </trans-unit>
-                       <trans-unit id="title">
-                               <source>TYPO3 Inline Help</source>
-                       </trans-unit>
-                       <trans-unit id="manual_title">
-                               <source>TYPO3 Inline User Manual</source>
-                       </trans-unit>
-                       <trans-unit id="introduction">
-                               <source>Introduction</source>
-                       </trans-unit>
-                       <trans-unit id="description">
-                               <source>The TYPO3 Inline User Manual is composed from the available help in this TYPO3 Installation (Context Sensitive Help). Here you will find a general description of the TYPO3 Core modules, installation specific Backend Modules and Database Tables that are available based on your login credentials.</source>
-                       </trans-unit>
-                       <trans-unit id="full_manual">
-                               <source>Full Manual (in one page)</source>
-                       </trans-unit>
-                       <trans-unit id="full_manual_chapters">
-                               <source>Manual Chapters</source>
-                       </trans-unit>
-               </body>
-       </file>
-</xliff>
diff --git a/typo3/sysext/documentation/Resources/Private/Layouts/ContextSensitiveHelp.html b/typo3/sysext/documentation/Resources/Private/Layouts/ContextSensitiveHelp.html
deleted file mode 100644 (file)
index 2738dec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="tx_cshmanual">
-       <f:render section="content" />
-
-       <hr />
-       <div class="t3-copyright-notice">
-
-               <p>
-                       <f:format.raw>{copyright}</f:format.raw>
-               </p>
-       </div>
-</div>
diff --git a/typo3/sysext/documentation/Resources/Private/Partials/Manual.html b/typo3/sysext/documentation/Resources/Private/Partials/Manual.html
deleted file mode 100644 (file)
index f62c253..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<a id="{manual.table}{f:if(condition:manual.field,then:'.{manual.field}')}"></a>
-
-<h2>{manual.headerLine}</h2>
-
-<p>{manual.content -> f:format.raw()}</p>
-
-<f:if condition="{manual.configuration.details}">
-       <h3>
-               <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:details" />
-       </h3>
-       {manual.configuration.details -> f:format.stripTags(allowedTags:'<strong><em><b><i>') -> f:format.nl2br()}
-</f:if>
-
-<f:if condition="{manual.configuration.syntax}">
-       <h3>
-               <f:translate key="LLL:EXT:documentation/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:documentation/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>
-
-                       </li>
-               </f:for>
-       </ul>
-</f:if>
diff --git a/typo3/sysext/documentation/Resources/Private/Partials/TableOfContents.html b/typo3/sysext/documentation/Resources/Private/Partials/TableOfContents.html
deleted file mode 100644 (file)
index 139e611..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
-
-<h1>
-       <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:manual_title" />
-</h1>
-<p class="lead">
-       <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:description" />
-</p>
-
-<h2>
-       <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:TOC" />
-</h2>
-
-<f:if condition="{toc}">
-       <ul>
-               <f:for each="{toc}" as="modules" key="type">
-                       <li>
-                               <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:TOC_{type}" default="{type}" />
-
-                               <ul>
-                                       <f:for each="{modules}" as="title" key="module">
-                                               <li>
-                                                       <f:if condition="{all}">
-                                                               <f:then>
-                                                                       <a href="#{module}">{module}</a>
-                                                               </f:then>
-                                                               <f:else>
-                                                                       <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'detail', table:module,field:'*'})}">
-                                                                               {title}
-                                                                       </a>
-                                                               </f:else>
-                                                       </f:if>
-                                               </li>
-                                       </f:for>
-                               </ul>
-                       </li>
-               </f:for>
-       </ul>
-</f:if>
-
-</html>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Help/All.html b/typo3/sysext/documentation/Resources/Private/Templates/Help/All.html
deleted file mode 100644 (file)
index 4172bcf..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<f:layout name="ContextSensitiveHelp" />
-
-<f:section name="content">
-       <f:render partial="TableOfContents" arguments="{toc:all.toc, all:1}" />
-
-       <f:for each="{all.content}" as="sections">
-               <f:for each="{sections.content}" as="item">
-                       <f:render partial="Manual" arguments="{manual:item}" />
-               </f:for>
-       </f:for>
-</f:section>
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Help/Detail.html b/typo3/sysext/documentation/Resources/Private/Templates/Help/Detail.html
deleted file mode 100644 (file)
index 01b3af0..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<f:layout name="ContextSensitiveHelp" />
-
-<f:section name="content">
-       <f:for each="{manuals}" as="manual">
-               <f:render partial="Manual" arguments="{manual:manual}" />
-       </f:for>
-</f:section>
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Help/Index.html b/typo3/sysext/documentation/Resources/Private/Templates/Help/Index.html
deleted file mode 100644 (file)
index 0af8979..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<html xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers">
-
-<f:layout name="ContextSensitiveHelp" />
-
-<f:section name="docheader">
-
-</f:section>
-<f:section name="content">
-       <f:render partial="TableOfContents" arguments="{toc:toc,all:0}" />
-
-       <a href="{be:moduleLink(route:'help_cshmanual',arguments:{action:'all'})}">
-               <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:full_manual" />
-       </a>
-</f:section>
-</html>
\ No newline at end of file
diff --git a/typo3/sysext/documentation/Resources/Public/Icons/module-cshmanual.svg b/typo3/sysext/documentation/Resources/Public/Icons/module-cshmanual.svg
deleted file mode 100644 (file)
index 6a5246a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill="#E49139" d="M0 0h64v64H0z"/><path fill="#FFF" d="M45 50H19c-.6 0-1-.4-1-1V15c0-.6.4-1 1-1h26c.6 0 1 .4 1 1v34c0 .6-.4 1-1 1z"/><path fill="#E49139" d="M20 16h2v32h-2zM26 18h16v2H26z"/></svg>
\ No newline at end of file
index ca14f39..cda46e4 100644 (file)
@@ -19,8 +19,7 @@
                "typo3/cms": "*"
        },
        "replace": {
-               "documentation": "*",
-               "typo3/cms-cshmanual": "*"
+               "documentation": "*"
        },
        "extra": {
                "branch-alias": {
@@ -28,8 +27,7 @@
                },
                "typo3/cms": {
                        "Package": {
-                               "partOfFactoryDefault": true,
-                               "partOfMinimalUsableSystem": true
+                               "partOfFactoryDefault": true
                        },
                        "extension-key": "documentation"
                },
index 6e66735..6ef8e4d 100644 (file)
@@ -9,5 +9,3 @@ defined('TYPO3_MODE') or die();
         \TYPO3\CMS\Documentation\Slots\ExtensionManager::class,
         'processActions'
     );
-
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook']['cshmanual'] = \TYPO3\CMS\Documentation\Service\JavaScriptService::class . '->addJavaScript';
index 216045d..91a95a6 100644 (file)
@@ -16,17 +16,3 @@ defined('TYPO3_MODE') or die();
         'labels' => 'LLL:EXT:documentation/Resources/Private/Language/locallang_mod.xlf',
     ]
 );
-
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addModule(
-    'help',
-    'cshmanual',
-    'top',
-    '',
-    [
-        'routeTarget' => \TYPO3\CMS\Documentation\Controller\HelpController::class . '::handleRequest',
-        'name' => 'help_cshmanual',
-        'access' => 'user,group',
-        'icon' => 'EXT:documentation/Resources/Public/Icons/module-cshmanual.svg',
-        'labels' => 'LLL:EXT:documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf',
-    ]
-);
index a559528..041b5de 100644 (file)
@@ -46,6 +46,7 @@ class BackendUserStartModuleUpdate extends AbstractUpdate
                     || $userConfig['startModule'] === 'help_AboutmodulesAboutmodules'
                     || $userConfig['startModule'] === 'help_AboutAboutmodules'
                     || $userConfig['startModule'] === 'help_CshmanualCshmanual'
+                    || $userConfig['startModule'] === 'help_DocumentationCshmanual'
                 ) {
                     $needsExecution = true;
                     break;
@@ -53,7 +54,7 @@ class BackendUserStartModuleUpdate extends AbstractUpdate
             }
         }
         if ($needsExecution) {
-            $description = 'The backend user setting startModule is changed for the extensions about/aboutmodules a d help/cshmanual. Update all'
+            $description = 'The backend user setting startModule is changed for the extensions about/aboutmodules and help/cshmanual. Update all'
                 . ' backend users that use EXT:aboutmodules and EXT:cshmanual as startModule.';
         }
         return $needsExecution;
@@ -78,8 +79,12 @@ class BackendUserStartModuleUpdate extends AbstractUpdate
                     || $userConfig['startModule'] === 'help_AboutmodulesAboutmodules'
                     || $userConfig['startModule'] === 'help_AboutAboutmodules'
                     || $userConfig['startModule'] === 'help_CshmanualCshmanual'
+                    || $userConfig['startModule'] === 'help_DocumentationCshmanual'
                 ) {
-                    $userConfig['startModule'] = $userConfig['startModule'] === 'help_CshmanualCshmanual' ? 'help_DocumentationCshmanual' : 'help_AboutAbout';
+                    $userConfig['startModule'] = 'help_AboutAbout';
+                    if ($userConfig['startModule'] === 'help_CshmanualCshmanual' || $userConfig['startModule'] === 'help_DocumentationCshmanual') {
+                        $userConfig['startModule'] = 'help_BackendCshmanual';
+                    }
                     $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
                     $queryBuilder->update('be_users')
                         ->where(