[TASK] Merge EXT:cshmanual into EXT:documentation 80/53180/10
authorGeorg Ringer <georg.ringer@gmail.com>
Fri, 9 Jun 2017 19:18:42 +0000 (21:18 +0200)
committerBenni Mack <benni@typo3.org>
Sat, 30 Sep 2017 20:17:16 +0000 (22:17 +0200)
To reduce the amount of system extensions the extension
cshmanual can be merged into EXT:documentation.

Resolves: #81574
Releases: master
Change-Id: I5cd728938ffd319f5c13bf0af4caeda48c08ee37
Reviewed-on: https://review.typo3.org/53180
Reviewed-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Tested-by: Mona Muzaffar <mona.muzaffar@gmx.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
43 files changed:
composer.json
composer.lock
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.js
typo3/sysext/core/Documentation/Changelog/master/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Acceptance/Backend/Extensionmanager/InstalledExtensionsCest.php
typo3/sysext/cshmanual/Classes/Controller/HelpController.php [deleted file]
typo3/sysext/cshmanual/Classes/Domain/Repository/TableManualRepository.php [deleted file]
typo3/sysext/cshmanual/Classes/Service/AccessService.php [deleted file]
typo3/sysext/cshmanual/Classes/Service/JavaScriptService.php [deleted file]
typo3/sysext/cshmanual/LICENSE.txt [deleted file]
typo3/sysext/cshmanual/Resources/Private/Language/locallang_mod_help_cshmanual.xlf [deleted file]
typo3/sysext/cshmanual/Resources/Private/Language/locallang_view_help.xlf [deleted file]
typo3/sysext/cshmanual/Resources/Private/Layouts/Default.html [deleted file]
typo3/sysext/cshmanual/Resources/Private/Partials/Manual.html [deleted file]
typo3/sysext/cshmanual/Resources/Private/Partials/TableOfContents.html [deleted file]
typo3/sysext/cshmanual/Resources/Private/Templates/Help/All.html [deleted file]
typo3/sysext/cshmanual/Resources/Private/Templates/Help/Detail.html [deleted file]
typo3/sysext/cshmanual/Resources/Private/Templates/Help/Index.html [deleted file]
typo3/sysext/cshmanual/Resources/Public/Icons/Extension.png [deleted file]
typo3/sysext/cshmanual/Resources/Public/Icons/module-cshmanual.svg [deleted file]
typo3/sysext/cshmanual/composer.json [deleted file]
typo3/sysext/cshmanual/ext_emconf.php [deleted file]
typo3/sysext/cshmanual/ext_tables.php [deleted file]
typo3/sysext/documentation/Classes/Controller/HelpController.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Service/AccessService.php [new file with mode: 0644]
typo3/sysext/documentation/Classes/Service/JavaScriptService.php [new file with mode: 0644]
typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php [new file with mode: 0644]
typo3/sysext/documentation/Migrations/Code/LegacyClassesForIde.php [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Language/locallang_view_help.xlf [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Layouts/ContextSensitiveHelp.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Partials/Manual.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Partials/TableOfContents.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Templates/Help/All.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Templates/Help/Detail.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Private/Templates/Help/Index.html [new file with mode: 0644]
typo3/sysext/documentation/Resources/Public/Icons/module-cshmanual.svg [new file with mode: 0644]
typo3/sysext/documentation/composer.json
typo3/sysext/documentation/ext_tables.php
typo3/sysext/install/Classes/Updates/BackendUserStartModuleUpdate.php [new file with mode: 0644]
typo3/sysext/install/ext_localconf.php

index ca60643..e3ae34b 100644 (file)
@@ -72,6 +72,7 @@
                        "always-add-alias-loader": true,
                        "class-alias-maps": [
                                "typo3/sysext/core/Migrations/Code/ClassAliasMap.php",
+                               "typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php",
                                "typo3/sysext/extbase/Migrations/Code/ClassAliasMap.php",
                                "typo3/sysext/fluid/Migrations/Code/ClassAliasMap.php",
                                "typo3/sysext/info/Migrations/Code/ClassAliasMap.php",
@@ -92,7 +93,6 @@
                "typo3/cms-beuser": "self.version",
                "typo3/cms-context-help": "self.version",
                "typo3/cms-core": "self.version",
-               "typo3/cms-cshmanual": "self.version",
                "typo3/cms-documentation": "self.version",
                "typo3/cms-extbase": "self.version",
                "typo3/cms-extensionmanager": "self.version",
                        "TYPO3\\CMS\\Belog\\": "typo3/sysext/belog/Classes/",
                        "TYPO3\\CMS\\Beuser\\": "typo3/sysext/beuser/Classes/",
                        "TYPO3\\CMS\\Core\\": "typo3/sysext/core/Classes/",
-                       "TYPO3\\CMS\\Cshmanual\\": "typo3/sysext/cshmanual/Classes/",
                        "TYPO3\\CMS\\Documentation\\": "typo3/sysext/documentation/Classes/",
                        "TYPO3\\CMS\\Extbase\\": "typo3/sysext/extbase/Classes/",
                        "TYPO3\\CMS\\Extensionmanager\\": "typo3/sysext/extensionmanager/Classes/",
index 789b997..105f18d 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "9ceecfd2a5223b2a9f1fb5589454cdf5",
+    "content-hash": "b054fb89baff8fbce0b4822829f871f3",
     "packages": [
         {
             "name": "cogpowered/finediff",
index d050d02..a7c6401 100644 (file)
@@ -2431,7 +2431,7 @@ class BackendUtility
         // @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('cshmanual')) {
+        if ((!empty($helpText) || $hasHelpTextOverload) && ExtensionManagementUtility::isLoaded('documentation')) {
             // If no text was given, just use the regular help icon
             if ($text == '') {
                 /** @var IconFactory $iconFactory */
index 4019d95..edf32e0 100644 (file)
@@ -112,8 +112,8 @@ define(['jquery', 'TYPO3/CMS/Backend/Popover', 'bootstrap'], function($, Popover
                try {
                        var cshWindow = window.open(
                                ContextHelp.helpModuleUrl +
-                                       '&tx_cshmanual_help_cshmanualcshmanual[table]=' + $trigger.data('table') +
-                                       '&tx_cshmanual_help_cshmanualcshmanual[field]=' + $trigger.data('field'),
+                                       '&tx_documentation_help_documentationcshmanual[table]=' + $trigger.data('table') +
+                                       '&tx_documentation_help_documentationcshmanual[field]=' + $trigger.data('field'),
                                'ContextHelpWindow',
                                'height=400,width=600,status=0,menubar=0,scrollbars=1'
                        );
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-81574-MergedSystemExtensionCshmanualIntoDocumentation.rst
new file mode 100644 (file)
index 0000000..5543d4b
--- /dev/null
@@ -0,0 +1,17 @@
+.. 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
index e78a526..e6782cb 100644 (file)
@@ -45,13 +45,13 @@ class InstalledExtensionsCest
         $I->canSeeNumberOfElements('#typo3-extension-list tbody tr[role="row"]', [10, 100]);
 
         // Fill extension search field
-        $I->fillField('Tx_Extensionmanager_extensionkey', 'cshmanual');
+        $I->fillField('Tx_Extensionmanager_extensionkey', 'documentation');
 
         // see 2 rows. 1 for the header and one for the result
         $I->canSeeNumberOfElements('#typo3-extension-list tbody tr[role="row"]', 1);
 
         // Look for extension key
-        $I->canSee('cshmanual', '#typo3-extension-list tbody tr[role="row"] td');
+        $I->canSee('documentation', '#typo3-extension-list tbody tr[role="row"] td');
 
         // unset the filter
         $I->waitForElementVisible('#Tx_Extensionmanager_extensionkey ~button.close', 1);
diff --git a/typo3/sysext/cshmanual/Classes/Controller/HelpController.php b/typo3/sysext/cshmanual/Classes/Controller/HelpController.php
deleted file mode 100644 (file)
index 06e2577..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-namespace TYPO3\CMS\Cshmanual\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 TYPO3\CMS\Backend\Template\Components\ButtonBar;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\View\BackendTemplateView;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Localization\LanguageService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Cshmanual\Domain\Repository\TableManualRepository;
-use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
-use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
-
-/**
- * Main help module controller
- */
-class HelpController extends ActionController
-{
-    /**
-     * Section identifiers
-     */
-    const FULL = 0;
-
-    /**
-     * Show only Table of contents
-     */
-    const TOC_ONLY = 1;
-
-    /**
-     * @var TableManualRepository
-     */
-    protected $tableManualRepository;
-
-    /**
-     * Default View Container
-     *
-     * @var BackendTemplateView
-     */
-    protected $defaultViewObjectName = BackendTemplateView::class;
-
-    /**
-     * Initialize the controller
-     */
-    public function initializeAction()
-    {
-        $this->tableManualRepository = GeneralUtility::makeInstance(TableManualRepository::class);
-    }
-
-    /**
-     * Initialize the view
-     *
-     * @param ViewInterface $view The view
-     */
-    public function initializeView(ViewInterface $view)
-    {
-        /** @var BackendTemplateView $view */
-        parent::initializeView($view);
-        $this->registerDocheaderButtons();
-        $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 string $table
-     * @param string $field
-     */
-    public function detailAction($table = '', $field = '*')
-    {
-        if (empty($table)) {
-            $this->forward('index');
-        }
-
-        $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
-     *
-     * @throws \InvalidArgumentException
-     */
-    protected function registerDocheaderButtons()
-    {
-        /** @var ButtonBar $buttonBar */
-        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
-        $currentRequest = $this->request;
-        $moduleName = $currentRequest->getPluginName();
-        $getVars = $this->request->getArguments();
-
-        $mayMakeShortcut = $this->getBackendUser()->mayMakeShortcut();
-
-        if ($mayMakeShortcut) {
-            $extensionName = $currentRequest->getControllerExtensionName();
-            if (count($getVars) === 0) {
-                $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName);
-                $getVars = ['id', 'route', $modulePrefix];
-            }
-            $shortcutButton = $buttonBar->makeShortcutButton()
-                ->setModuleName($moduleName)
-                ->setGetVariables($getVars);
-            $buttonBar->addButton($shortcutButton);
-        }
-        if (isset($getVars['action']) && $getVars['action'] !== 'index') {
-            $backButton = $buttonBar->makeLinkButton()
-                ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:back'))
-                ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL))
-                ->setHref(BackendUtility::getModuleUrl($moduleName));
-            $buttonBar->addButton($backButton);
-        }
-    }
-
-    /**
-     * Returns the currently logged in BE user
-     *
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-
-    /**
-     * Returns the LanguageService
-     *
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-}
diff --git a/typo3/sysext/cshmanual/Classes/Domain/Repository/TableManualRepository.php b/typo3/sysext/cshmanual/Classes/Domain/Repository/TableManualRepository.php
deleted file mode 100644 (file)
index d283e4f..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-<?php
-namespace TYPO3\CMS\Cshmanual\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\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\PathUtility;
-
-/**
- * Tabble manual repository
- */
-class TableManualRepository
-{
-    /**
-     * @var \TYPO3\CMS\Cshmanual\Service\AccessService
-     */
-    protected $accessService;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->accessService = GeneralUtility::makeInstance(\TYPO3\CMS\Cshmanual\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\Cshmanual\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
-        $keyName = $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);
-                    $imgInfo = @getimagesize($absImagePath);
-                    if (is_array($imgInfo)) {
-                        $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/cshmanual/Classes/Service/AccessService.php b/typo3/sysext/cshmanual/Classes/Service/AccessService.php
deleted file mode 100644 (file)
index 755ceff..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-namespace TYPO3\CMS\Cshmanual\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/cshmanual/Classes/Service/JavaScriptService.php b/typo3/sysext/cshmanual/Classes/Service/JavaScriptService.php
deleted file mode 100644 (file)
index 76503ce..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-namespace TYPO3\CMS\Cshmanual\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\Backend\Utility\BackendUtility;
-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)) {
-            $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
-            $pageRenderer->addInlineSetting('ContextHelp', 'moduleUrl', BackendUtility::getModuleUrl('help_CshmanualCshmanual', [
-                'tx_cshmanual_help_cshmanualcshmanual' => [
-                    'controller' => 'Help',
-                    'action' => 'detail'
-                ]
-            ]));
-        }
-    }
-
-    /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBeUser()
-    {
-        return isset($GLOBALS['BE_USER']) ? $GLOBALS['BE_USER'] : null;
-    }
-}
diff --git a/typo3/sysext/cshmanual/LICENSE.txt b/typo3/sysext/cshmanual/LICENSE.txt
deleted file mode 100644 (file)
index 95d36a7..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-Some icons used in the TYPO3 project are retrieved from the "Silk" icon set of
-Mark James, which can be found at http://famfamfam.com/lab/icons/silk/. This
-set is distributed under a Creative Commons Attribution 2.5 License. The
-license can be found at http://creativecommons.org/licenses/by/2.5/.
----------------------------------
-
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/typo3/sysext/cshmanual/Resources/Private/Language/locallang_mod_help_cshmanual.xlf b/typo3/sysext/cshmanual/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/cshmanual/Resources/Private/Language/locallang_view_help.xlf b/typo3/sysext/cshmanual/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/cshmanual/Resources/Private/Layouts/Default.html b/typo3/sysext/cshmanual/Resources/Private/Layouts/Default.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/cshmanual/Resources/Private/Partials/Manual.html b/typo3/sysext/cshmanual/Resources/Private/Partials/Manual.html
deleted file mode 100644 (file)
index 5b7015c..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:cshmanual/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:cshmanual/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:cshmanual/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/cshmanual/Resources/Private/Partials/TableOfContents.html b/typo3/sysext/cshmanual/Resources/Private/Partials/TableOfContents.html
deleted file mode 100644 (file)
index 5c7c9f1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<h1>
-       <f:translate key="LLL:EXT:cshmanual/Resources/Private/Language/locallang_view_help.xlf:manual_title" />
-</h1>
-<p class="lead">
-       <f:translate key="LLL:EXT:cshmanual/Resources/Private/Language/locallang_view_help.xlf:description" />
-</p>
-
-<h2>
-       <f:translate key="LLL:EXT:cshmanual/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:cshmanual/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>
-                                                                       <f:link.action action="detail" arguments="{table:module,field:'*'}">{title}</f:link.action>
-                                                               </f:else>
-                                                       </f:if>
-                                               </li>
-                                       </f:for>
-                               </ul>
-                       </li>
-               </f:for>
-       </ul>
-</f:if>
diff --git a/typo3/sysext/cshmanual/Resources/Private/Templates/Help/All.html b/typo3/sysext/cshmanual/Resources/Private/Templates/Help/All.html
deleted file mode 100644 (file)
index 976ddde..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<f:layout name="Default" />
-
-<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>
\ No newline at end of file
diff --git a/typo3/sysext/cshmanual/Resources/Private/Templates/Help/Detail.html b/typo3/sysext/cshmanual/Resources/Private/Templates/Help/Detail.html
deleted file mode 100644 (file)
index 314bdd7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{namespace csh=TYPO3\CMS\Cshmanual\ViewHelpers}
-<f:layout name="Default" />
-
-<f:section name="content">
-       <f:for each="{manuals}" as="manual">
-               <f:render partial="Manual" arguments="{manual:manual}" />
-       </f:for>
-</f:section>
\ No newline at end of file
diff --git a/typo3/sysext/cshmanual/Resources/Private/Templates/Help/Index.html b/typo3/sysext/cshmanual/Resources/Private/Templates/Help/Index.html
deleted file mode 100644 (file)
index 7749c00..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<f:layout name="Default" />
-
-<f:section name="docheader">
-
-</f:section>
-<f:section name="content">
-
-       <f:render partial="TableOfContents" arguments="{toc:toc,all:0}" />
-
-       <f:link.action action="all">
-               <f:translate key="LLL:EXT:cshmanual/Resources/Private/Language/locallang_view_help.xlf:full_manual" />
-       </f:link.action>
-</f:section>
diff --git a/typo3/sysext/cshmanual/Resources/Public/Icons/Extension.png b/typo3/sysext/cshmanual/Resources/Public/Icons/Extension.png
deleted file mode 100644 (file)
index 7be668c..0000000
Binary files a/typo3/sysext/cshmanual/Resources/Public/Icons/Extension.png and /dev/null differ
diff --git a/typo3/sysext/cshmanual/Resources/Public/Icons/module-cshmanual.svg b/typo3/sysext/cshmanual/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
diff --git a/typo3/sysext/cshmanual/composer.json b/typo3/sysext/cshmanual/composer.json
deleted file mode 100644 (file)
index d28159b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-       "name": "typo3/cms-cshmanual",
-       "type": "typo3-cms-framework",
-       "description": "Shows TYPO3 inline user manual.",
-       "homepage": "https://typo3.org",
-       "license": ["GPL-2.0+"],
-       "authors": [{
-                       "name": "TYPO3 Core Team",
-                       "email": "typo3cms@typo3.org",
-                       "role": "Developer"
-               }],
-
-       "require": {
-               "typo3/cms-core": ">=9.0.0 <=9.0.99"
-       },
-       "conflict": {
-               "typo3/cms": "*"
-       },
-       "replace": {
-               "cshmanual": "*"
-       },
-       "extra": {
-               "branch-alias": {
-                       "dev-master": "9.x-dev"
-               },
-               "typo3/cms": {
-                       "Package": {
-                               "protected": false,
-                               "partOfFactoryDefault": true,
-                               "partOfMinimalUsableSystem": true
-                       },
-                       "extension-key": "cshmanual"
-               }
-       },
-       "autoload": {
-               "psr-4": {
-                       "TYPO3\\CMS\\Cshmanual\\": "Classes/"
-               }
-       }
-}
diff --git a/typo3/sysext/cshmanual/ext_emconf.php b/typo3/sysext/cshmanual/ext_emconf.php
deleted file mode 100644 (file)
index 26e2afc..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-$EM_CONF[$_EXTKEY] = [
-    'title' => 'Help>TYPO3 Manual',
-    'description' => 'Shows TYPO3 inline user manual.',
-    'category' => 'module',
-    'state' => 'stable',
-    'uploadfolder' => 0,
-    'createDirs' => '',
-    'clearCacheOnLoad' => 0,
-    'author' => 'TYPO3 Core Team',
-    'author_email' => 'typo3cms@typo3.org',
-    'author_company' => '',
-    'version' => '9.0.0',
-    'constraints' => [
-        'depends' => [
-            'typo3' => '9.0.0-9.0.99',
-        ],
-        'conflicts' => [],
-        'suggests' => [],
-    ],
-];
diff --git a/typo3/sysext/cshmanual/ext_tables.php b/typo3/sysext/cshmanual/ext_tables.php
deleted file mode 100644 (file)
index 8055c54..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-defined('TYPO3_MODE') or die();
-
-if (TYPO3_MODE === 'BE') {
-    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
-        'TYPO3.CMS.Cshmanual',
-        'help',
-        'cshmanual',
-        'top',
-        [
-            'Help' => 'index,all,detail',
-        ],
-        [
-            'access' => 'user,group',
-            'icon' => 'EXT:cshmanual/Resources/Public/Icons/module-cshmanual.svg',
-            'labels' => 'LLL:EXT:cshmanual/Resources/Private/Language/locallang_mod_help_cshmanual.xlf',
-        ]
-    );
-
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook']['cshmanual'] = \TYPO3\CMS\Cshmanual\Service\JavaScriptService::class . '->addJavaScript';
-}
diff --git a/typo3/sysext/documentation/Classes/Controller/HelpController.php b/typo3/sysext/documentation/Classes/Controller/HelpController.php
new file mode 100644 (file)
index 0000000..09653d3
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+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 TYPO3\CMS\Backend\Template\Components\ButtonBar;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\View\BackendTemplateView;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+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\Extbase\Mvc\Controller\ActionController;
+use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
+
+/**
+ * Main help module controller
+ */
+class HelpController extends ActionController
+{
+    /**
+     * Section identifiers
+     */
+    const FULL = 0;
+
+    /**
+     * Show only Table of contents
+     */
+    const TOC_ONLY = 1;
+
+    /**
+     * @var TableManualRepository
+     */
+    protected $tableManualRepository;
+
+    /**
+     * Default View Container
+     *
+     * @var BackendTemplateView
+     */
+    protected $defaultViewObjectName = BackendTemplateView::class;
+
+    /**
+     * Initialize the controller
+     */
+    public function initializeAction()
+    {
+        $this->tableManualRepository = GeneralUtility::makeInstance(TableManualRepository::class);
+    }
+
+    /**
+     * Initialize the view
+     *
+     * @param ViewInterface $view The view
+     */
+    public function initializeView(ViewInterface $view)
+    {
+        /** @var BackendTemplateView $view */
+        parent::initializeView($view);
+        $this->registerDocheaderButtons();
+        $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 string $table
+     * @param string $field
+     */
+    public function detailAction($table = '', $field = '*')
+    {
+        if (empty($table)) {
+            $this->forward('index');
+        }
+
+        $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
+     *
+     * @throws \InvalidArgumentException
+     */
+    protected function registerDocheaderButtons()
+    {
+        /** @var ButtonBar $buttonBar */
+        $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
+        $currentRequest = $this->request;
+        $moduleName = $currentRequest->getPluginName();
+        $getVars = $this->request->getArguments();
+
+        $mayMakeShortcut = $this->getBackendUser()->mayMakeShortcut();
+
+        if ($mayMakeShortcut) {
+            $extensionName = $currentRequest->getControllerExtensionName();
+            if (count($getVars) === 0) {
+                $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName);
+                $getVars = ['id', 'route', $modulePrefix];
+            }
+            $shortcutButton = $buttonBar->makeShortcutButton()
+                ->setModuleName($moduleName)
+                ->setGetVariables($getVars);
+            $buttonBar->addButton($shortcutButton);
+        }
+        if (isset($getVars['action']) && $getVars['action'] !== 'index') {
+            $backButton = $buttonBar->makeLinkButton()
+                ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_common.xlf:back'))
+                ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL))
+                ->setHref(BackendUtility::getModuleUrl($moduleName));
+            $buttonBar->addButton($backButton);
+        }
+    }
+
+    /**
+     * Returns the currently logged in BE user
+     *
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
+
+    /**
+     * Returns the LanguageService
+     *
+     * @return LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+}
diff --git a/typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php b/typo3/sysext/documentation/Classes/Domain/Repository/TableManualRepository.php
new file mode 100644 (file)
index 0000000..d115ef6
--- /dev/null
@@ -0,0 +1,417 @@
+<?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\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
+        $keyName = $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);
+                    $imgInfo = @getimagesize($absImagePath);
+                    if (is_array($imgInfo)) {
+                        $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
new file mode 100644 (file)
index 0000000..7d83205
--- /dev/null
@@ -0,0 +1,46 @@
+<?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
new file mode 100644 (file)
index 0000000..ad916ea
--- /dev/null
@@ -0,0 +1,57 @@
+<?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\Backend\Utility\BackendUtility;
+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)) {
+            $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
+            $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/ContextHelp');
+            $pageRenderer->addInlineSetting('ContextHelp', 'moduleUrl', BackendUtility::getModuleUrl('help_DocumentationCshmanual', [
+                'tx_documentation_help_documentationcshmanual' => [
+                    'controller' => 'Help',
+                    'action' => 'detail'
+                ]
+            ]));
+        }
+    }
+
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBeUser()
+    {
+        return isset($GLOBALS['BE_USER']) ? $GLOBALS['BE_USER'] : null;
+    }
+}
diff --git a/typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php b/typo3/sysext/documentation/Migrations/Code/ClassAliasMap.php
new file mode 100644 (file)
index 0000000..e4960e9
--- /dev/null
@@ -0,0 +1,6 @@
+<?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
new file mode 100644 (file)
index 0000000..d4b2b7f
--- /dev/null
@@ -0,0 +1,22 @@
+<?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
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/documentation/Resources/Private/Language/locallang_view_help.xlf b/typo3/sysext/documentation/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/documentation/Resources/Private/Layouts/ContextSensitiveHelp.html b/typo3/sysext/documentation/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/documentation/Resources/Private/Partials/Manual.html b/typo3/sysext/documentation/Resources/Private/Partials/Manual.html
new file mode 100644 (file)
index 0000000..f62c253
--- /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: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
new file mode 100644 (file)
index 0000000..89bd677
--- /dev/null
@@ -0,0 +1,35 @@
+<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>
+                                                                       <f:link.action action="detail" arguments="{table:module,field:'*'}">{title}</f:link.action>
+                                                               </f:else>
+                                                       </f:if>
+                                               </li>
+                                       </f:for>
+                               </ul>
+                       </li>
+               </f:for>
+       </ul>
+</f:if>
diff --git a/typo3/sysext/documentation/Resources/Private/Templates/Help/All.html b/typo3/sysext/documentation/Resources/Private/Templates/Help/All.html
new file mode 100644 (file)
index 0000000..4172bcf
--- /dev/null
@@ -0,0 +1,11 @@
+<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
new file mode 100644 (file)
index 0000000..01b3af0
--- /dev/null
@@ -0,0 +1,7 @@
+<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
new file mode 100644 (file)
index 0000000..718bad3
--- /dev/null
@@ -0,0 +1,12 @@
+<f:layout name="ContextSensitiveHelp" />
+
+<f:section name="docheader">
+
+</f:section>
+<f:section name="content">
+       <f:render partial="TableOfContents" arguments="{toc:toc,all:0}" />
+
+       <f:link.action action="all">
+               <f:translate key="LLL:EXT:documentation/Resources/Private/Language/locallang_view_help.xlf:full_manual" />
+       </f:link.action>
+</f:section>
diff --git a/typo3/sysext/documentation/Resources/Public/Icons/module-cshmanual.svg b/typo3/sysext/documentation/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 c149f01..9fe7b54 100644 (file)
@@ -9,7 +9,6 @@
                        "email": "typo3cms@typo3.org",
                        "role": "Developer"
                }],
-
        "require": {
                "typo3/cms-core": ">=9.0.0 <=9.0.99"
        },
@@ -17,7 +16,9 @@
                "typo3/cms": "*"
        },
        "replace": {
-               "documentation": "*"
+               "documentation": "*",
+               "csh_manual": "*",
+               "typo3/cms-cshmanual": "*"
        },
        "extra": {
                "branch-alias": {
                },
                "typo3/cms": {
                        "Package": {
-                               "partOfFactoryDefault": true
+                               "partOfFactoryDefault": true,
+                               "partOfMinimalUsableSystem": true
                        },
                        "extension-key": "documentation"
+               },
+               "typo3/class-alias-loader": {
+                       "class-alias-maps": [
+                               "Migrations/Code/ClassAliasMap.php"
+                       ]
                }
        },
        "autoload": {
index f719ca7..4ac5d81 100644 (file)
@@ -17,4 +17,21 @@ if (TYPO3_MODE === 'BE') {
             'labels' => 'LLL:EXT:documentation/Resources/Private/Language/locallang_mod.xlf',
         ]
     );
+
+    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
+        'TYPO3.CMS.Documentation',
+        'help',
+        'cshmanual',
+        'top',
+        [
+            'Help' => 'index,all,detail',
+        ],
+        [
+            'access' => 'user,group',
+            'icon' => 'EXT:documentation/Resources/Public/Icons/module-cshmanual.svg',
+            'labels' => 'LLL:EXT:documentation/Resources/Private/Language/locallang_mod_help_cshmanual.xlf',
+        ]
+    );
+
+    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook']['cshmanual'] = \TYPO3\CMS\Documentation\Service\JavaScriptService::class . '->addJavaScript';
 }
diff --git a/typo3/sysext/install/Classes/Updates/BackendUserStartModuleUpdate.php b/typo3/sysext/install/Classes/Updates/BackendUserStartModuleUpdate.php
new file mode 100644 (file)
index 0000000..a559528
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+namespace TYPO3\CMS\Install\Updates;
+
+/*
+ * 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\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Update backend user setting startModule if set to "help_aboutmodules" or "help_CshmanualCshmanual"
+ */
+class BackendUserStartModuleUpdate extends AbstractUpdate
+{
+    /**
+     * @var string
+     */
+    protected $title = 'Update backend user setting "startModule"';
+
+    /**
+     * Checks if an update is needed
+     *
+     * @param string &$description The description for the update
+     * @return bool Whether an update is needed (TRUE) or not (FALSE)
+     */
+    public function checkForUpdate(&$description)
+    {
+        $statement = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable('be_users')
+            ->select(['uid', 'uc'], 'be_users', []);
+        $needsExecution = false;
+        while ($backendUser = $statement->fetch()) {
+            if ($backendUser['uc'] !== null) {
+                $userConfig = unserialize($backendUser['uc'], ['allowed_classes' => false]);
+                if ($userConfig['startModule'] === 'help_aboutmodules'
+                    || $userConfig['startModule'] === 'help_AboutmodulesAboutmodules'
+                    || $userConfig['startModule'] === 'help_AboutAboutmodules'
+                    || $userConfig['startModule'] === 'help_CshmanualCshmanual'
+                ) {
+                    $needsExecution = true;
+                    break;
+                }
+            }
+        }
+        if ($needsExecution) {
+            $description = 'The backend user setting startModule is changed for the extensions about/aboutmodules a d help/cshmanual. Update all'
+                . ' backend users that use EXT:aboutmodules and EXT:cshmanual as startModule.';
+        }
+        return $needsExecution;
+    }
+
+    /**
+     * Performs the database update if backend user's startmodule is
+     * "help_aboutmodules" or "help_AboutmodulesAboutmodules" or "help_CshmanualCshmanual"
+     *
+     * @param array &$databaseQueries Queries done in this update
+     * @param string &$customMessage Custom message
+     * @return bool
+     */
+    public function performUpdate(array &$databaseQueries, &$customMessage)
+    {
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
+        $statement = $queryBuilder->select('uid', 'uc')->from('be_users')->execute();
+        while ($backendUser = $statement->fetch()) {
+            if ($backendUser['uc'] !== null) {
+                $userConfig = unserialize($backendUser['uc'], ['allowed_classes' => false]);
+                if ($userConfig['startModule'] === 'help_aboutmodules'
+                    || $userConfig['startModule'] === 'help_AboutmodulesAboutmodules'
+                    || $userConfig['startModule'] === 'help_AboutAboutmodules'
+                    || $userConfig['startModule'] === 'help_CshmanualCshmanual'
+                ) {
+                    $userConfig['startModule'] = $userConfig['startModule'] === 'help_CshmanualCshmanual' ? 'help_DocumentationCshmanual' : 'help_AboutAbout';
+                    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
+                    $queryBuilder->update('be_users')
+                        ->where(
+                            $queryBuilder->expr()->eq(
+                                'uid',
+                                $queryBuilder->createNamedParameter($backendUser['uid'], \PDO::PARAM_INT)
+                            )
+                        )
+                        // Manual quoting and false as third parameter to have the final
+                        // value in $databaseQueries and not a statement placeholder
+                        ->set('uc', serialize($userConfig));
+                    $databaseQueries[] = $queryBuilder->getSQL();
+                    $queryBuilder->execute();
+                }
+            }
+        }
+        return true;
+    }
+}
index 229f515..aa610a1 100644 (file)
@@ -48,6 +48,8 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['separateSysH
     = \TYPO3\CMS\Install\Updates\SeparateSysHistoryFromSysLogUpdate::class;
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['rdctExtension']
     = \TYPO3\CMS\Install\Updates\RedirectExtractionUpdate::class;
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['cshmanualBackendUsers']
+    = \TYPO3\CMS\Install\Updates\BackendUserStartModuleUpdate::class;
 
 $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
 $icons = [