[!!!][FEATURE] ElementBrowser refactoring, LinkBrowser API - Part 2 38/43938/19
authorMarkus Klein <markus.klein@typo3.org>
Thu, 8 Oct 2015 23:35:09 +0000 (01:35 +0200)
committerFrank Nägler <frank.naegler@typo3.org>
Tue, 3 Nov 2015 12:17:00 +0000 (13:17 +0100)
Adjust link browser integration of RTE.

This removes the dedicated tree classes for RTE as those are useless
by now. Additionally the ElementBrowser class is finally removed.

Resolves: #66369
Releases: master
Change-Id: I8f42228cb3c4b3008d3f0acaa014d01733f6186d
Reviewed-on: https://review.typo3.org/43938
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Frank Nägler <frank.naegler@typo3.org>
Tested-by: Frank Nägler <frank.naegler@typo3.org>
43 files changed:
typo3/sysext/backend/Classes/Controller/FileSystemNavigationFrameController.php
typo3/sysext/backend/Classes/Controller/LinkBrowserController.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Tree/View/ElementBrowserPageTreeView.php
typo3/sysext/backend/Classes/Tree/View/FolderTreeView.php
typo3/sysext/backend/Configuration/Backend/AjaxRoutes.php
typo3/sysext/backend/Configuration/Backend/Routes.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js [new file with mode: 0644]
typo3/sysext/compatibility6/Configuration/TCA/Overrides/tt_content.php
typo3/sysext/compatibility6/Migrations/Code/ClassAliasMap.php
typo3/sysext/compatibility6/Migrations/Code/LegacyClassesForIde.php
typo3/sysext/core/Classes/Migrations/TcaMigration.php
typo3/sysext/core/Configuration/TCA/sys_file_reference.php
typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php
typo3/sysext/frontend/Configuration/TCA/tt_content.php
typo3/sysext/impexp/Tests/Functional/Fixtures/Extensions/impexp_group_files/Configuration/TCA/tx_impexpgroupfiles_item.php
typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php [deleted file]
typo3/sysext/recordlist/Classes/Browser/FileBrowser.php
typo3/sysext/recordlist/Classes/Browser/FolderBrowser.php
typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php [new file with mode: 0644]
typo3/sysext/recordlist/Classes/Controller/ElementBrowserController.php
typo3/sysext/recordlist/Classes/Controller/LinkBrowserController.php [deleted file]
typo3/sysext/recordlist/Classes/LinkHandler/AbstractLinkHandler.php
typo3/sysext/recordlist/Classes/LinkHandler/FileLinkHandler.php
typo3/sysext/recordlist/Classes/LinkHandler/LinkHandlerInterface.php
typo3/sysext/recordlist/Classes/LinkHandler/MailLinkHandler.php
typo3/sysext/recordlist/Classes/LinkHandler/PageLinkHandler.php
typo3/sysext/recordlist/Classes/Tree/View/DummyLinkParameterProvider.php
typo3/sysext/recordlist/Configuration/Backend/AjaxRoutes.php [deleted file]
typo3/sysext/recordlist/Configuration/Backend/Routes.php
typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js
typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js
typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js
typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js
typo3/sysext/rtehtmlarea/Classes/BrowseLinks.php [deleted file]
typo3/sysext/rtehtmlarea/Classes/Controller/BrowseLinksController.php
typo3/sysext/rtehtmlarea/Classes/FolderTree.php [deleted file]
typo3/sysext/rtehtmlarea/Classes/LinkHandler/RemoveLinkHandler.php [deleted file]
typo3/sysext/rtehtmlarea/Classes/PageTree.php [deleted file]
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/Plugins/TYPO3Link.js
typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/RteLinkBrowser.js

index 303bd5f..2ac7cf1 100644 (file)
@@ -118,8 +118,7 @@ class FileSystemNavigationFrameController
             if ($this->foldertree instanceof ElementBrowserFolderTreeView) {
                 // create a fake provider to pass link data along properly
                 $linkParamProvider = GeneralUtility::makeInstance(DummyLinkParameterProvider::class,
-                    $this->scopeData['browser']['mode'],
-                    $this->scopeData['browser']['act'],
+                    $this->scopeData['browser'],
                     $this->scopeData['script']
                 );
                 $this->foldertree->setLinkParameterProvider($linkParamProvider);
diff --git a/typo3/sysext/backend/Classes/Controller/LinkBrowserController.php b/typo3/sysext/backend/Classes/Controller/LinkBrowserController.php
new file mode 100644 (file)
index 0000000..3ef5c46
--- /dev/null
@@ -0,0 +1,165 @@
+<?php
+namespace TYPO3\CMS\Backend\Controller;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Page\PageRenderer;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
+use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
+
+/**
+ * Extended controller for link browser
+ */
+class LinkBrowserController extends AbstractLinkBrowserController {
+
+    /**
+     * Initialize $this->currentLinkParts
+     *
+     * @return void
+     */
+    protected function initCurrentUrl()
+    {
+        $currentLink = isset($this->parameters['currentValue']) ? trim($this->parameters['currentValue']) : '';
+        $currentLinkParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($currentLink);
+        $currentLinkParts['params'] = $currentLinkParts['additionalParams'];
+        unset($currentLinkParts['additionalParams']);
+
+        $this->currentLinkParts = $currentLinkParts;
+
+        parent::initCurrentUrl();
+    }
+
+    /**
+     * Initialize document template object
+     *
+     * @return void
+     */
+    protected function initDocumentTemplate()
+    {
+        parent::initDocumentTemplate();
+
+        if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(true)) {
+            $this->parameters['fieldChangeFunc'] = array();
+        }
+        unset($this->parameters['fieldChangeFunc']['alert']);
+        $update = [];
+        foreach ($this->parameters['fieldChangeFunc'] as $v) {
+            $update[] = 'parent.opener.' . $v;
+        }
+        $inlineJS = implode(LF, $update);
+
+        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
+        $pageRenderer->loadJquery();
+        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter', 'function(FormEngineLinkBrowserAdapter) {
+                       FormEngineLinkBrowserAdapter.updateFunctions = function() {' . $inlineJS . '};
+               }');
+    }
+
+    /**
+     * Encode a typolink via ajax
+     *
+     * This avoids to implement the encoding functionality again in JS for the browser.
+     *
+     * @param ServerRequestInterface $request
+     * @param ResponseInterface $response
+     * @return ResponseInterface
+     */
+    public function encodeTypoLink(ServerRequestInterface $request, ResponseInterface $response)
+    {
+        $typoLinkParts = $request->getQueryParams();
+        if (isset($typoLinkParts['params'])) {
+            $typoLinkParts['additionalParams'] = $typoLinkParts['params'];
+            unset($typoLinkParts['params']);
+        }
+
+        $typoLink = GeneralUtility::makeInstance(TypoLinkCodecService::class)->encode($typoLinkParts);
+
+        $response->getBody()->write(json_encode(['typoLink' => $typoLink]));
+        return $response;
+    }
+
+    /**
+     * Determines whether submitted field change functions are valid
+     * and are coming from the system and not from an external abuse.
+     *
+     * @param bool $handleFlexformSections Whether to handle flexform sections differently
+     * @return bool Whether the submitted field change functions are valid
+     */
+    protected function areFieldChangeFunctionsValid($handleFlexformSections = false)
+    {
+        $result = false;
+        if (isset($this->parameters['fieldChangeFunc']) && is_array($this->parameters['fieldChangeFunc']) && isset($this->parameters['fieldChangeFuncHash'])) {
+            $matches = array();
+            $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i';
+            $fieldChangeFunctions = $this->parameters['fieldChangeFunc'];
+            // Special handling of flexform sections:
+            // Field change functions are modified in JavaScript, thus the hash is always invalid
+            if ($handleFlexformSections && preg_match($pattern, $this->parameters['itemName'], $matches)) {
+                $originalName = $matches[1];
+                $cleanedName = $matches[2] . $matches[4];
+                foreach ($fieldChangeFunctions as &$value) {
+                    $value = str_replace($originalName, $cleanedName, $value);
+                }
+                unset($value);
+            }
+            $result = $this->parameters['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions));
+        }
+        return $result;
+    }
+
+    /**
+     * Get attributes for the body tag
+     *
+     * @return string[] Array of body-tag attributes
+     */
+    protected function getBodyTagAttributes()
+    {
+        $parameters = parent::getBodyTagAttributes();
+
+        $formEngineParameters['fieldChangeFunc'] = $this->parameters['fieldChangeFunc'];
+        $formEngineParameters['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->parameters['fieldChangeFunc']));
+
+        $parameters['data-add-on-params'] .= GeneralUtility::implodeArrayForUrl('P', $formEngineParameters);
+
+        return $parameters;
+    }
+
+    /**
+     * Return the ID of current page
+     *
+     * @return int
+     */
+    protected function getCurrentPageId()
+    {
+        $pageId = 0;
+        $browserParameters = $this->parameters;
+        if (isset($browserParameters['pid'])) {
+            $pageId = $browserParameters['pid'];
+        } elseif (isset($browserParameters['itemName'])) {
+            // parse data[<table>][<uid>]
+            if (preg_match('~data\[([^]]*)\]\[([^]]*)\]~', $browserParameters['itemName'], $matches)) {
+                $recordArray = BackendUtility::getRecord($matches['1'], $matches['2']);
+                if (is_array($recordArray)) {
+                    $pageId = $recordArray['pid'];
+                }
+            }
+        }
+        return (int)$pageId;
+    }
+
+}
index d0fa418..432fe24 100644 (file)
@@ -82,7 +82,7 @@ class ElementBrowserPageTreeView extends BrowseTreeView
     public function wrapTitle($title, $v, $ext_pArrPages = false)
     {
         if ($this->ext_isLinkable($v['doktype'], $v['uid'])) {
-            return '<span class="list-tree-title"><a href="#" class="t3-js-pageLink" data-id="' . (int)$v['uid'] . '">' . $title . '</a></span>';
+            return '<span class="list-tree-title"><a href="#" class="t3js-pageLink" data-id="' . (int)$v['uid'] . '">' . $title . '</a></span>';
         } else {
             return '<span class="list-tree-title text-muted">' . $title . '</span>';
         }
@@ -122,7 +122,9 @@ class ElementBrowserPageTreeView extends BrowseTreeView
             }
             $urlParameters = $this->linkParameterProvider->getUrlParameters(['pid' => (int)$treeItem['row']['uid']]);
             $aOnClick = 'return jumpToUrl(' . GeneralUtility::quoteJSvalue($this->getThisScript() . ltrim(GeneralUtility::implodeArrayForUrl('', $urlParameters), '&')) . ');';
-            $cEbullet = $this->ext_isLinkable($treeItem['row']['doktype'], $treeItem['row']['uid']) ? '<a href="#" class="list-tree-show" onclick="' . htmlspecialchars($aOnClick) . '"><i class="fa fa-caret-square-o-right"></i></a>' : '';
+            $cEbullet = $this->ext_isLinkable($treeItem['row']['doktype'], $treeItem['row']['uid'])
+                ? '<a href="#" class="list-tree-show" onclick="' . htmlspecialchars($aOnClick) . '"><i class="fa fa-caret-square-o-right"></i></a>'
+                : '';
             $out .= '
                                <li' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '') . '>
                                        <span class="list-tree-group' . $selected . '">
@@ -147,8 +149,7 @@ class ElementBrowserPageTreeView extends BrowseTreeView
                 }
             }
         }
-        $out = '<ul class="list-tree list-tree-root">' . $out . '</ul>';
-        return $out;
+        return '<ul class="list-tree list-tree-root">' . $out . '</ul>';
     }
 
     /**
index 776c64c..c43b238 100644 (file)
@@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Resource\Folder;
 use TYPO3\CMS\Core\Resource\FolderInterface;
 use TYPO3\CMS\Core\Resource\InaccessibleFolder;
+use TYPO3\CMS\Core\Resource\ResourceStorage;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Lang\LanguageService;
 
@@ -33,7 +34,7 @@ class FolderTreeView extends AbstractTreeView
     /**
      * The users' file Storages
      *
-     * @var \TYPO3\CMS\Core\Resource\ResourceStorage[]
+     * @var ResourceStorage[]
      */
     protected $storages = null;
 
@@ -99,11 +100,12 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Generate the plus/minus icon for the browsable tree.
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject Entry folder object
+     * @param Folder $folderObject Entry folder object
      * @param int $subFolderCounter The current entry number
      * @param int $totalSubFolders The total number of entries. If equal to $a, a "bottom" element is returned.
      * @param int $nextCount The number of sub-elements to the current element.
      * @param bool $isExpanded The element was expanded to render subelements if this flag is set.
+     *
      * @return string Image tag with the plus/minus icon.
      * @internal
      * @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::PMicon()
@@ -163,7 +165,8 @@ class FolderTreeView extends AbstractTreeView
      * Wrapping the folder icon
      *
      * @param string $icon The image tag for the icon
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The row for the current element
+     * @param Folder $folderObject The row for the current element
+     *
      * @return string The processed icon input value.
      * @internal
      */
@@ -188,8 +191,9 @@ class FolderTreeView extends AbstractTreeView
      * Wrapping $title in a-tags.
      *
      * @param string $title Title string
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject the folder record
+     * @param Folder $folderObject the folder record
      * @param int $bank Bank pointer (which mount point number)
+     *
      * @return string
      * @internal
      */
@@ -208,7 +212,8 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Returns the id from the record - for folders, this is an md5 hash.
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
+     * @param Folder $folderObject The folder object
+     *
      * @return int The "uid" field value.
      */
     public function getId($folderObject)
@@ -219,7 +224,8 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Returns jump-url parameter value.
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
+     * @param Folder $folderObject The folder object
+     *
      * @return string The jump-url parameter.
      */
     public function getJumpToParam($folderObject)
@@ -243,8 +249,9 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Returns the value for the image "title" attribute
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder to be used
-     * @return         string The attribute value (is htmlspecialchared() already)
+     * @param Folder $folderObject The folder to be used
+     *
+     * @return string The attribute value (is htmlspecialchared() already)
      */
     public function getTitleAttrib($folderObject)
     {
@@ -275,10 +282,10 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Get a tree for one storage
      *
-     * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
+     * @param ResourceStorage $storageObject
      * @return void
      */
-    public function getBrowseableTreeForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject)
+    public function getBrowseableTreeForStorage(ResourceStorage $storageObject)
     {
         // If there are filemounts, show each, otherwise just the rootlevel folder
         $fileMounts = $storageObject->getFileMounts();
@@ -300,7 +307,7 @@ class FolderTreeView extends AbstractTreeView
         $this->reset();
         // Go through all "root level folders" of this tree (can be the rootlevel folder or any file mount points)
         foreach ($rootLevelFolders as $rootLevelFolderInfo) {
-            /** @var $rootLevelFolder \TYPO3\CMS\Core\Resource\Folder */
+            /** @var $rootLevelFolder Folder */
             $rootLevelFolder = $rootLevelFolderInfo['folder'];
             $rootLevelFolderName = $rootLevelFolderInfo['name'];
             $folderHashSpecUID = GeneralUtility::md5int($rootLevelFolder->getCombinedIdentifier());
@@ -352,13 +359,14 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Fetches the data for the tree
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject the folderobject
+     * @param Folder $folderObject the folderobject
      * @param int $depth Max depth (recursivity limit)
      * @param string $type HTML-code prefix for recursive calls.
+     *
      * @return int The count of items on the level
      * @see getBrowsableTree()
      */
-    public function getFolderTree(\TYPO3\CMS\Core\Resource\Folder $folderObject, $depth = 999, $type = '')
+    public function getFolderTree(Folder $folderObject, $depth = 999, $type = '')
     {
         $depth = (int)$depth;
 
@@ -476,7 +484,7 @@ class FolderTreeView extends AbstractTreeView
         // so we know how many we have to close when all children are done rendering
         $closeDepth = array();
         foreach ($treeItems as $treeItem) {
-            /** @var $folderObject \TYPO3\CMS\Core\Resource\Folder */
+            /** @var $folderObject Folder */
             $folderObject = $treeItem['row']['folder'];
             $classAttr = $treeItem['row']['_CSSCLASS'];
             $folderIdentifier = $folderObject->getCombinedIdentifier();
@@ -543,10 +551,11 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Counts the number of directories in a file path.
      *
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject File path.
+     * @param Folder $folderObject File path.
+     *
      * @return int
      */
-    public function getNumberOfSubfolders(\TYPO3\CMS\Core\Resource\Folder $folderObject)
+    public function getNumberOfSubfolders(Folder $folderObject)
     {
         $subFolders = $folderObject->getSubfolders();
         return count($subFolders);
@@ -585,11 +594,12 @@ class FolderTreeView extends AbstractTreeView
     /**
      * Helper method to map md5-hash to shorter number
      *
-     * @param \TYPO3\CMS\Core\Resource\ResourceStorage $storageObject
-     * @param \TYPO3\CMS\Core\Resource\Folder $startingPointFolder
+     * @param ResourceStorage $storageObject
+     * @param Folder $startingPointFolder
+     *
      * @return int
      */
-    protected function getShortHashNumberForStorage(\TYPO3\CMS\Core\Resource\ResourceStorage $storageObject = null, \TYPO3\CMS\Core\Resource\Folder $startingPointFolder = null)
+    protected function getShortHashNumberForStorage(ResourceStorage $storageObject = null, Folder $startingPointFolder = null)
     {
         if (!$this->storageHashNumbers) {
             $this->storageHashNumbers = array();
@@ -657,11 +667,12 @@ class FolderTreeView extends AbstractTreeView
      *
      * @param string $mountKey The mount key / storage UID
      * @param bool $doExpand Whether to expand/collapse
-     * @param \TYPO3\CMS\Core\Resource\Folder $folderObject The folder object
+     * @param Folder $folderObject The folder object
      * @param string $treeName The name of the tree
+     *
      * @return string
      */
-    protected function generateExpandCollapseParameter($mountKey = null, $doExpand = false, \TYPO3\CMS\Core\Resource\Folder $folderObject = null, $treeName = null)
+    protected function generateExpandCollapseParameter($mountKey = null, $doExpand = false, Folder $folderObject = null, $treeName = null)
     {
         $parts = array(
             $mountKey !== null ? $mountKey : $this->bank,
index a71417a..3ba27a8 100644 (file)
@@ -192,5 +192,11 @@ return [
     'icons' => [
         'path' => '/icons',
         'target' => \TYPO3\CMS\Core\Imaging\IconFactory::class . '::processAjaxRequest'
-    ]
+    ],
+
+    // Encode typolink parts on demand
+    'link_browser_encodetypolink' => [
+        'path' => '/link-browser/encode-typolink',
+        'target' => \TYPO3\CMS\Backend\Controller\LinkBrowserController::class . '::encodeTypoLink',
+    ],
 ];
index 98e02cc..60d1e8f 100644 (file)
@@ -80,6 +80,11 @@ return [
         'target' => Controller\Wizard\EditController::class . '::mainAction'
     ],
 
+    // Register link wizard
+    'wizard_link' => [
+        'path' => '/wizard/link/browse',
+        'target' => \TYPO3\CMS\Backend\Controller\LinkBrowserController::class . '::mainAction'
+    ],
 
     /** File- and folder-related routes */
 
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js
new file mode 100644 (file)
index 0000000..440d240
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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!
+ */
+
+/**
+ * Module: TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter
+ * LinkBrowser communication with parent window
+ */
+define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
+       'use strict';
+
+       /**
+        *
+        * @type {{updateFunctions: null}}
+        * @exports TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter
+        */
+       var FormEngineLinkBrowserAdapter = {
+               updateFunctions: null // those are set in the module initializer function in PHP
+       };
+
+       /**
+        * Return reference to parent's form element
+        *
+        * @returns {Element}
+        */
+       FormEngineLinkBrowserAdapter.checkReference = function () {
+               var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]';
+               if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) {
+                       return window.opener.document.querySelector(selector);
+               } else {
+                       close();
+               }
+       };
+
+       /**
+        * Save the current link back to the opener
+        *
+        * @param {String} input
+        */
+       LinkBrowser.finalizeFunction = function(input) {
+               var field = FormEngineLinkBrowserAdapter.checkReference();
+               if (field) {
+                       var attributeValues = LinkBrowser.getLinkAttributeValues();
+
+                       // remove page: prefix from page links
+                       if (input.indexOf('page:') === 0) {
+                               input = input.substr(5);
+                       }
+
+                       // remove the mailto: prefix from mail links
+                       if (input.indexOf('mailto:') === 0) {
+                               input = input.substr(7);
+                       }
+
+                       // remove http:// schema for external links
+                       if (attributeValues['data-htmlarea-external'] && input.substr(0, 7) === "http://") {
+                               input = input.substr(7);
+                       }
+
+                       // encode link on server
+                       attributeValues.url = input;
+
+                       $.ajax({
+                               url: TYPO3.settings.ajaxUrls['link_browser_encodetypolink'],
+                               data: attributeValues,
+                               method: 'GET',
+                               async: false, // todo: check if we can use promises
+                               success: function(data) {
+                                       if (data.typoLink) {
+                                               field.value = data.typoLink;
+                                               if (typeof field.onchange === 'function') {
+                                                       field.onchange();
+                                               }
+
+                                               FormEngineLinkBrowserAdapter.updateFunctions();
+
+                                               close();
+                                       }
+                               }
+                       });
+               }
+       };
+
+       return FormEngineLinkBrowserAdapter;
+});
index ac9e222..eda7dd9 100644 (file)
@@ -61,7 +61,7 @@ $extraContentColumns = array(
                     'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:image_link_formlabel',
                     'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif',
                     'module' => array(
-                        'name' => 'wizard_link_browser',
+                        'name' => 'wizard_link',
                     ),
                     'JSopenParams' => 'width=800,height=600,status=0,menubar=0,scrollbars=1'
                 )
@@ -128,7 +128,7 @@ $extraContentColumns = array(
                     'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:image_link_formlabel',
                     'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif',
                     'module' => array(
-                        'name' => 'wizard_link_browser',
+                        'name' => 'wizard_link',
                     ),
                     'params' => array(
                         'blindLinkOptions' => 'folder,file,mail,spec',
index afeb235..2933911 100644 (file)
@@ -175,7 +175,6 @@ return array(
     't3lib_TCEmain' => \TYPO3\CMS\Core\DataHandling\DataHandler::class,
     't3lib_TCEmain_checkModifyAccessListHook' => \TYPO3\CMS\Core\DataHandling\DataHandlerCheckModifyAccessListHookInterface::class,
     't3lib_TCEmain_processUploadHook' => \TYPO3\CMS\Core\DataHandling\DataHandlerProcessUploadHookInterface::class,
-    't3lib_browseLinksHook' => \TYPO3\CMS\Core\ElementBrowser\ElementBrowserHookInterface::class,
     't3lib_codec_JavaScriptEncoder' => \TYPO3\CMS\Core\Encoder\JavaScriptEncoder::class,
     't3lib_error_AbstractExceptionHandler' => \TYPO3\CMS\Core\Error\AbstractExceptionHandler::class,
     't3lib_error_DebugExceptionHandler' => \TYPO3\CMS\Core\Error\DebugExceptionHandler::class,
@@ -1058,7 +1057,6 @@ return array(
     'tx_openid_store' => \TYPO3\CMS\Openid\OpenidStore::class,
     'SC_mod_web_perm_ajax' => \TYPO3\CMS\Beuser\Controller\PermissionAjaxController::class,
     'SC_mod_web_perm_index' => \TYPO3\CMS\Beuser\Controller\PermissionController::class,
-    'browse_links' => \TYPO3\CMS\Recordlist\Browser\ElementBrowser::class,
     'SC_browse_links' => \TYPO3\CMS\Recordlist\Controller\ElementBrowserController::class,
     'SC_browser' => \TYPO3\CMS\Recordlist\Controller\ElementBrowserFramesetController::class,
     'SC_db_list' => \TYPO3\CMS\Recordlist\RecordList::class,
@@ -1097,7 +1095,6 @@ return array(
     'tx_rsaauth_session_storage' => \TYPO3\CMS\Rsaauth\Storage\SessionStorage::class,
     'tx_rsaauth_split_storage' => \TYPO3\CMS\Rsaauth\Storage\SplitStorage::class,
     'tx_rsaauth_storagefactory' => \TYPO3\CMS\Rsaauth\Storage\StorageFactory::class,
-    'tx_rtehtmlarea_browse_links' => \TYPO3\CMS\Rtehtmlarea\BrowseLinks::class,
     'tx_rtehtmlarea_parse_html' => \TYPO3\CMS\Rtehtmlarea\Controller\ParseHtmlController::class,
     'tx_rtehtmlarea_SC_browse_links' => \TYPO3\CMS\Rtehtmlarea\Controller\BrowseLinksController::class,
     'tx_rtehtmlarea_pi3' => \TYPO3\CMS\Rtehtmlarea\Controller\CustomAttributeController::class,
@@ -1136,16 +1133,12 @@ return array(
     'tx_rtehtmlarea_typo3link' => \TYPO3\CMS\Rtehtmlarea\Extension\Typo3Link::class,
     'tx_rtehtmlarea_undoredo' => \TYPO3\CMS\Rtehtmlarea\Extension\UndoRedo::class,
     'tx_rtehtmlarea_userelements' => \TYPO3\CMS\Rtehtmlarea\Extension\UserElements::class,
-    'tx_rtehtmlarea_folderTree' => \TYPO3\CMS\Rtehtmlarea\FolderTree::class,
     'tx_rtehtmlarea_deprecatedRteProperties' => \TYPO3\CMS\Rtehtmlarea\Hook\Install\DeprecatedRteProperties::class,
     'tx_rtehtmlarea_softrefproc' => \TYPO3\CMS\Rtehtmlarea\Hook\SoftReferenceHook::class,
     'tx_rtehtmlarea_statusReport_conflictsCheck' => \TYPO3\CMS\Rtehtmlarea\Hook\StatusReportConflictsCheckHook::class,
-    'tx_rtehtmlarea_image_folderTree' => \TYPO3\CMS\Rtehtmlarea\FolderTree::class,
-    'tx_rtehtmlarea_pageTree' => \TYPO3\CMS\Rtehtmlarea\PageTree::class,
     'tx_rtehtmlarea_api' => \TYPO3\CMS\Rtehtmlarea\RteHtmlAreaApi::class,
     'tx_rtehtmlarea_select_image' => \TYPO3\CMS\Rtehtmlarea\SelectImage::class,
     'tx_rtehtmlarea_user' => \TYPO3\CMS\Rtehtmlarea\Controller\UserElementsController::class,
-    'TYPO3\\CMS\\Rtehtmlarea\\ImageFolderTree' => \TYPO3\CMS\Rtehtmlarea\FolderTree::class,
     'tx_saltedpasswords_eval_be' => \TYPO3\CMS\Saltedpasswords\Evaluation\BackendEvaluator::class,
     'tx_saltedpasswords_eval' => \TYPO3\CMS\Saltedpasswords\Evaluation\Evaluator::class,
     'tx_saltedpasswords_eval_fe' => \TYPO3\CMS\Saltedpasswords\Evaluation\FrontendEvaluator::class,
index 50b6757..7bfe626 100644 (file)
@@ -1229,13 +1229,6 @@ interface t3lib_TCEmain_processUploadHook extends \TYPO3\CMS\Core\DataHandling\D
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-interface t3lib_browseLinksHook extends \TYPO3\CMS\Core\ElementBrowser\ElementBrowserHookInterface
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 class t3lib_codec_JavaScriptEncoder extends \TYPO3\CMS\Core\Encoder\JavaScriptEncoder
 {
 }
@@ -7361,13 +7354,6 @@ class SC_mod_web_perm_index extends \TYPO3\CMS\Beuser\Controller\PermissionContr
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-class browse_links extends \TYPO3\CMS\Recordlist\Browser\ElementBrowser
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 class SC_browse_links extends \TYPO3\CMS\Recordlist\Controller\ElementBrowserController
 {
 }
@@ -7634,13 +7620,6 @@ class tx_rsaauth_storagefactory extends \TYPO3\CMS\Rsaauth\Storage\StorageFactor
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-class tx_rtehtmlarea_browse_links extends \TYPO3\CMS\Rtehtmlarea\BrowseLinks
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 class tx_rtehtmlarea_parse_html extends \TYPO3\CMS\Rtehtmlarea\Controller\ParseHtmlController
 {
 }
@@ -7907,13 +7886,6 @@ class tx_rtehtmlarea_userelements extends \TYPO3\CMS\Rtehtmlarea\Extension\UserE
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-class tx_rtehtmlarea_folderTree extends \TYPO3\CMS\Rtehtmlarea\FolderTree
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 class tx_rtehtmlarea_deprecatedRteProperties extends \TYPO3\CMS\Rtehtmlarea\Hook\Install\DeprecatedRteProperties
 {
 }
@@ -7935,20 +7907,6 @@ class tx_rtehtmlarea_statusReport_conflictsCheck extends \TYPO3\CMS\Rtehtmlarea\
 /**
  * @deprecated since 6.0, removed since 7.0
  */
-class tx_rtehtmlarea_image_folderTree extends \TYPO3\CMS\Rtehtmlarea\FolderTree
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
-class tx_rtehtmlarea_pageTree extends \TYPO3\CMS\Rtehtmlarea\PageTree
-{
-}
-
-/**
- * @deprecated since 6.0, removed since 7.0
- */
 class tx_rtehtmlarea_api extends \TYPO3\CMS\Rtehtmlarea\RteHtmlAreaApi
 {
 }
index ad1372c..ea73593 100644 (file)
@@ -615,7 +615,7 @@ class TcaMigration
     }
 
     /**
-     * Migrate wizard "wizard_element_browser" used in mode "wizard" to use the "wizard_link_browser" instead
+     * Migrate wizard "wizard_element_browser" used in mode "wizard" to use the "wizard_link" instead
      *
      * @param array $tca
      * @return array Migrated TCA
@@ -631,12 +631,12 @@ class TcaMigration
                     isset($fieldConfig['config']['wizards']['link']['module']['name']) && $fieldConfig['config']['wizards']['link']['module']['name'] === 'wizard_element_browser'
                     && isset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']) &&  $fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode'] === 'wizard'
                 ) {
-                    $fieldConfig['config']['wizards']['link']['module']['name'] = 'wizard_link_browser';
+                    $fieldConfig['config']['wizards']['link']['module']['name'] = 'wizard_link';
                     unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']);
                     if (empty($fieldConfig['config']['wizards']['link']['module']['urlParameters'])) {
                         unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']);
                     }
-                    $this->messages[] = 'Reference to "wizard_element_browser" was migrated to new "wizard_link_browser" for field "' . $fieldName . '" in TCA table "' . $table . '"';
+                    $this->messages[] = 'Reference to "wizard_element_browser" was migrated to new "wizard_link" for field "' . $fieldName . '" in TCA table "' . $table . '"';
                 }
             }
         }
index a9417e8..606b709 100644 (file)
@@ -184,7 +184,7 @@ return array(
                         'title' => 'LLL:EXT:lang/locallang_tca.xlf:sys_file_reference.link',
                         'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif',
                         'module' => array(
-                            'name' => 'wizard_link_browser',
+                            'name' => 'wizard_link',
                         ),
                         'JSopenParams' => 'width=800,height=600,status=0,menubar=0,scrollbars=1'
                     )
index 3698654..1274454 100644 (file)
@@ -1010,7 +1010,7 @@ class TcaMigrationTest extends UnitTestCase
                             'wizards' => [
                                 'link' => [
                                     'module' => [
-                                        'name' => 'wizard_link_browser',
+                                        'name' => 'wizard_link',
                                     ],
                                 ],
                             ],
index 0313895..e66bd42 100644 (file)
@@ -334,7 +334,7 @@ return array(
                         'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:header_link_formlabel',
                         'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif',
                         'module' => array(
-                            'name' => 'wizard_link_browser',
+                            'name' => 'wizard_link',
                         ),
                         'JSopenParams' => 'width=800,height=600,status=0,menubar=0,scrollbars=1'
                     )
index 4298b12..513bbeb 100644 (file)
@@ -152,7 +152,7 @@ return array(
                                                                                                                                <title>Link</title>
                                                                                                                                <icon>EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_link.gif</icon>
                                                                                                                                <module type="array">
-                                                                                                                                       <name>wizard_link_browser</name>
+                                                                                                                                       <name>wizard_link</name>
                                                                                                                                </module>
                                                                                                                                <JSopenParams>width=800,height=600,status=0,menubar=0,scrollbars=1</JSopenParams>
                                                                                                                        </link>
diff --git a/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php b/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
deleted file mode 100755 (executable)
index 3aacf84..0000000
+++ /dev/null
@@ -1,2728 +0,0 @@
-<?php
-namespace TYPO3\CMS\Recordlist\Browser;
-
-/*
- * 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\RecordList\ElementBrowserRecordList;
-use TYPO3\CMS\Backend\Routing\Router;
-use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Backend\Template\DocumentTemplate;
-use TYPO3\CMS\Backend\Tree\View\ElementBrowserFolderTreeView;
-use TYPO3\CMS\Backend\Tree\View\ElementBrowserPageTreeView;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Database\DatabaseConnection;
-use TYPO3\CMS\Core\ElementBrowser\ElementBrowserHookInterface;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Imaging\IconFactory;
-use TYPO3\CMS\Core\Messaging\FlashMessage;
-use TYPO3\CMS\Core\Resource\FileRepository;
-use TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry;
-use TYPO3\CMS\Core\Page\PageRenderer;
-use TYPO3\CMS\Core\Resource\Exception;
-use TYPO3\CMS\Core\Resource\File;
-use TYPO3\CMS\Core\Resource\FileInterface;
-use TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter;
-use TYPO3\CMS\Core\Resource\Folder;
-use TYPO3\CMS\Core\Resource\InaccessibleFolder;
-use TYPO3\CMS\Core\Resource\ProcessedFile;
-use TYPO3\CMS\Core\Resource\ResourceFactory;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\StringUtility;
-use TYPO3\CMS\Core\Utility\MathUtility;
-use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
-use TYPO3\CMS\Lang\LanguageService;
-
-/**
- * class for the Element Browser window.
- */
-class ElementBrowser
-{
-    /**
-     * Optional instance of a record list that TBE_expandPage() should
-     * use to render the records in a page
-     *
-     * @var ElementBrowserRecordList
-     */
-    protected $recordList = null;
-
-    /**
-     * Current site URL (Frontend)
-     *
-     * @var string
-     * @internal
-     */
-    public $siteURL;
-
-    /**
-     * the script to link to
-     *
-     * @var string
-     */
-    public $thisScript;
-
-    /**
-     * RTE configuration
-     *
-     * @var array
-     */
-    protected $RTEProperties = array();
-
-    /**
-     * Target (RTE specific)
-     *
-     * @var string
-     */
-    public $setTarget;
-
-    /**
-     * CSS Class (RTE specific)
-     *
-     * @var string
-     */
-    public $setClass;
-
-    /**
-     * title (RTE specific)
-     *
-     * @var string
-     */
-    public $setTitle;
-
-    /**
-     * @var string
-     */
-    public $setParams;
-
-    /**
-     * Backend template object
-     *
-     * @var DocumentTemplate
-     */
-    public $doc;
-
-    /**
-     * Holds information about files
-     *
-     * @var mixed[][]
-     */
-    public $elements = array();
-
-    /**
-     * The mode determines the main kind of output from the element browser.
-     * There are these options for values: rte, db, file, filedrag, wizard.
-     * "rte" will show the link selector for the Rich Text Editor (see main_rte())
-     * "db" will allow you to browse for pages or records in the page tree (for TCEforms, see main_db())
-     * "file"/"filedrag" will allow you to browse for files or folders in the folder mounts (for TCEforms, main_file())
-     * "wizard" will allow you to browse for links (like "rte") which are passed back to TCEforms (see main_rte(1))
-     *
-     * @see main()
-     * @var string
-     */
-    public $mode;
-
-    /**
-     * Link selector action.
-     * page,file,url,mail are allowed values.
-     * These are only important with the link selector function and in that case they switch
-     * between the various menu options.
-     *
-     * @var string
-     */
-    public $act;
-
-    /**
-     * When you click a page title/expand icon to see the content of a certain page, this
-     * value will contain that value (the ID of the expanded page). If the value is NOT set,
-     * then it will be restored from the module session data (see main(), mode="db")
-     *
-     * @var NULL|int
-     */
-    public $expandPage;
-
-    /**
-     * When you click a folder name/expand icon to see the content of a certain file folder,
-     * this value will contain that value (the path of the expanded file folder). If the
-     * value is NOT set, then it will be restored from the module session data (see main(),
-     * mode="file"/"filedrag"). Example value: "/www/htdocs/typo3/32/3dsplm/fileadmin/css/"
-     *
-     * @var string
-     */
-    public $expandFolder;
-
-    /**
-     * the folder object of a parent folder that was selected
-     *
-     * @var Folder
-     */
-    protected $selectedFolder;
-
-    /**
-     * TYPO3 Element Browser, wizard mode parameters. There is a heap of parameters there,
-     * better debug() them out if you need something... :-)
-     *
-     * @var array[]
-     */
-    public $P;
-
-    /**
-     * Active with TYPO3 Element Browser: Contains the name of the form field for which this window
-     * opens - thus allows us to make references back to the main window in which the form is.
-     * Example value: "data[pages][39][bodytext]|||tt_content|"
-     * or "data[tt_content][NEW3fba56fde763d][image]|||gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai|"
-     *
-     * Values:
-     * 0: form field name reference, eg. "data[tt_content][123][image]"
-     * 1: htmlArea RTE parameters: editorNo:contentTypo3Language
-     * 2: RTE config parameters: RTEtsConfigParams
-     * 3: allowed types. Eg. "tt_content" or "gif,jpg,jpeg,tif,bmp,pcx,tga,png,pdf,ai"
-     * 4: IRRE uniqueness: target level object-id to perform actions/checks on, eg. "data[79][tt_address][1][<field>][<foreign_table>]"
-     * 5: IRRE uniqueness: name of function in opener window that checks if element is already used, eg. "inline.checkUniqueElement"
-     * 6: IRRE uniqueness: name of function in opener window that performs some additional(!) action, eg. "inline.setUniqueElement"
-     * 7: IRRE uniqueness: name of function in opener window that performs action instead of using addElement/insertElement, eg. "inline.importElement"
-     *
-     * $pArr = explode('|', $this->bparams);
-     * $formFieldName = $pArr[0];
-     * $allowedTablesOrFileTypes = $pArr[3];
-     *
-     * @var string
-     */
-    public $bparams;
-
-    /**
-     * Used with the Rich Text Editor.
-     * Example value: "tt_content:NEW3fba58c969f5c:bodytext:23:text:23:"
-     *
-     * @var string
-     */
-    public $RTEtsConfigParams;
-
-    /**
-     * Plus/Minus icon value. Used by the tree class to open/close notes on the trees.
-     *
-     * @var string
-     */
-    public $PM;
-
-    /**
-     * Pointer, used when browsing a long list of records etc.
-     *
-     * @var int
-     */
-    public $pointer;
-
-    /**
-     * Used with the link selector: Contains the GET input information about the CURRENT link
-     * in the RTE/TCEform field. This consists of "href", "target" and "title" keys.
-     * This information is passed around in links.
-     *
-     * @var array[]
-     */
-    public $curUrlArray;
-
-    /**
-     * Used with the link selector: Contains a processed version of the input values from curUrlInfo.
-     * This is splitted into pageid, content element id, label value etc.
-     * This is used for the internal processing of that information.
-     *
-     * @var array[]
-     */
-    public $curUrlInfo;
-
-    /**
-     * array which holds hook objects (initialised in init())
-     *
-     * @var ElementBrowserHookInterface[]
-     */
-    protected $hookObjects = array();
-
-    /**
-     * @var string
-     */
-    protected $hookName = 'typo3/class.browse_links.php';
-
-    /**
-     * @var PageRenderer
-     */
-    protected $pageRenderer = null;
-
-    /**
-     * @var IconFactory
-     */
-    protected $iconFactory;
-
-    /**
-     * @var string
-     */
-    protected $searchWord;
-
-    /**
-     * @var FileRepository
-     */
-    protected $fileRepository;
-
-    /**
-    * Construct
-    */
-    public function __construct()
-    {
-        $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
-        $this->fileRepository = GeneralUtility::makeInstance(FileRepository::class);
-        $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-        $this->pageRenderer->loadJquery();
-        $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
-    }
-
-    /**
-     * Sets the script url depending on being a module or script request
-     */
-    protected function determineScriptUrl()
-    {
-        if ($routePath = GeneralUtility::_GP('route')) {
-            $router = GeneralUtility::makeInstance(Router::class);
-            $route = $router->match($routePath);
-            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-            $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'));
-        } elseif ($moduleName = GeneralUtility::_GP('M')) {
-            $this->thisScript = BackendUtility::getModuleUrl($moduleName);
-        } else {
-            $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
-        }
-    }
-
-    /**
-     * Calculate path to this script.
-     * This method is public, to be used in hooks of this class only.
-     *
-     * @return string
-     */
-    public function getThisScript()
-    {
-        return strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&';
-    }
-
-    /**
-     * Constructor:
-     * Initializes a lot of variables, setting JavaScript functions in header etc.
-     *
-     * @return void
-     * @throws \UnexpectedValueException
-     */
-    public function init()
-    {
-        $this->initVariables();
-        $this->initDocumentTemplate();
-
-        // Initializing hooking browsers
-        $this->initHookObjects();
-
-        $this->initCurrentUrl();
-
-        // Determine nature of current url:
-        $this->act = GeneralUtility::_GP('act');
-        if (!$this->act) {
-            $this->act = $this->curUrlInfo['act'];
-        }
-
-        $this->initLinkAttributes();
-
-        // Finally, add the accumulated JavaScript to the template object:
-        // also unset the default jumpToUrl() function before
-        unset($this->doc->JScodeArray['jumpToUrl']);
-        $this->doc->JScode .= $this->doc->wrapScriptTags($this->getJSCode());
-    }
-
-    /**
-     * Initialize class variables
-     *
-     * @return void
-     */
-    public function initVariables()
-    {
-        // Main GPvars:
-        $this->pointer = GeneralUtility::_GP('pointer');
-        $this->bparams = GeneralUtility::_GP('bparams');
-        $this->P = GeneralUtility::_GP('P');
-        $this->expandPage = GeneralUtility::_GP('expandPage');
-        $this->expandFolder = GeneralUtility::_GP('expandFolder');
-        $this->PM = GeneralUtility::_GP('PM');
-        $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
-        $this->searchWord = (string)GeneralUtility::_GP('searchWord');
-
-        // Site URL
-        // Current site url
-        $this->siteURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
-        $this->determineScriptUrl();
-
-        // Default mode is RTE
-        $this->mode = GeneralUtility::_GP('mode');
-        if (!$this->mode) {
-            $this->mode = 'rte';
-        }
-
-        // Rich Text Editor specific configuration:
-        if ($this->mode === 'rte') {
-            $this->RTEProperties = $this->getRTEConfig();
-        }
-    }
-
-    /**
-     * Initialize document template object
-     *
-     *  @return void
-     */
-    protected function initDocumentTemplate()
-    {
-        // Creating backend template object:
-        $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
-        $this->doc->bodyTagId = 'typo3-browse-links-php';
-        $this->doc->getContextMenuCode();
-
-        $pageRenderer = $this->getPageRenderer();
-        $pageRenderer->loadJquery();
-        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/BrowseFiles');
-    }
-
-    /**
-     * Initialize hook objects implementing the interface
-     *
-     * @throws \UnexpectedValueException
-     * @return void
-     */
-    protected function initHookObjects()
-    {
-        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['browseLinksHook'])) {
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['browseLinksHook'] as $classData) {
-                $processObject = GeneralUtility::getUserObj($classData);
-                if (!$processObject instanceof ElementBrowserHookInterface) {
-                    throw new \UnexpectedValueException('$processObject must implement interface ' . ElementBrowserHookInterface::class, 1195039394);
-                }
-                $parameters = array();
-                $processObject->init($this, $parameters);
-                $this->hookObjects[] = $processObject;
-            }
-        }
-    }
-
-    /**
-     * Initialize $this->curUrlArray and $this->curUrlInfo based on script parameters
-     *
-     * @return void
-     */
-    protected function initCurrentUrl()
-    {
-        // CurrentUrl - the current link url must be passed around if it exists
-        if ($this->mode === 'wizard') {
-            $currentValues = GeneralUtility::trimExplode(LF, trim($this->P['currentValue']));
-            if (!empty($currentValues)) {
-                $currentValue = array_pop($currentValues);
-            } else {
-                $currentValue = '';
-            }
-            $currentLinkParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($currentValue);
-
-            $initialCurUrlArray = array(
-                'href' => $currentLinkParts['url'],
-                'target' => $currentLinkParts['target'],
-                'class' => $currentLinkParts['class'],
-                'title' => $currentLinkParts['title'],
-                'params' => $currentLinkParts['additionalParams']
-            );
-            $this->curUrlArray = is_array(GeneralUtility::_GP('curUrl'))
-                ? array_merge($initialCurUrlArray, GeneralUtility::_GP('curUrl'))
-                : $initialCurUrlArray;
-            // Additional fields for page links
-            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendUrlArray'])
-                && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendUrlArray'])
-            ) {
-                $conf = array();
-                $_params = array(
-                    'conf' => &$conf,
-                    'linkParts' => [
-                        // the hook expects old numerical indexes
-                        $currentLinkParts['url'],
-                        $currentLinkParts['target'],
-                        $currentLinkParts['class'],
-                        $currentLinkParts['title'],
-                        $currentLinkParts['additionalParams']
-                    ]
-                );
-                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendUrlArray'] as $objRef) {
-                    $processor =& GeneralUtility::getUserObj($objRef);
-                    $processor->extendUrlArray($_params, $this);
-                }
-            }
-            $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
-            // pageid == 0 means that this is not an internal (page) link
-            if ($this->curUrlInfo['pageid'] == 0 && $this->curUrlArray['href']) {
-                // Check if there is the FAL API
-                if (GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'file:')) {
-                    $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
-                } elseif (file_exists(PATH_site . rawurldecode($this->curUrlArray['href']))) {
-                    $this->curUrlInfo = $this->parseCurUrl($this->siteURL . $this->curUrlArray['href'], $this->siteURL);
-                } elseif (strstr($this->curUrlArray['href'], '@')) {
-                    $this->curUrlInfo = $this->parseCurUrl('mailto:' . $this->curUrlArray['href'], $this->siteURL);
-                } else {
-                    // nothing of the above. this is an external link
-                    if (strpos($this->curUrlArray['href'], '://') === false) {
-                        $currentLinkParts['url'] = 'http://' . $this->curUrlArray['href'];
-                    }
-                    $this->curUrlInfo = $this->parseCurUrl($currentLinkParts['url'], $this->siteURL);
-                }
-            } elseif (!$this->curUrlArray['href']) {
-                $this->curUrlInfo = array();
-                $this->act = 'page';
-            } else {
-                $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
-            }
-        } else {
-            // RTE only
-            $this->curUrlArray = GeneralUtility::_GP('curUrl');
-            if ($this->curUrlArray['all']) {
-                $this->curUrlArray = GeneralUtility::get_tag_attributes($this->curUrlArray['all']);
-                $this->curUrlArray['href'] = htmlspecialchars_decode($this->curUrlArray['href']);
-            }
-            // Note: parseCurUrl will invoke the hooks
-            $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
-            if (isset($this->curUrlArray['data-htmlarea-external']) && $this->curUrlArray['data-htmlarea-external'] === '1' && $this->curUrlInfo['act'] !== 'mail') {
-                $this->curUrlInfo['act'] = 'url';
-                $this->curUrlInfo['info'] = $this->curUrlArray['href'];
-            }
-        }
-    }
-
-    /**
-     * Initialize the current or default values of the link attributes (RTE)
-     *
-     * @return void
-     */
-    protected function initLinkAttributes()
-    {
-        $this->setTarget = $this->curUrlArray['target'] != '-' ? $this->curUrlArray['target'] : '';
-        if ($this->RTEProperties['default.']['defaultLinkTarget'] && !isset($this->curUrlArray['target'])) {
-            $this->setTarget = $this->RTEProperties['default.']['defaultLinkTarget'];
-        }
-        $this->setClass = $this->curUrlArray['class'] != '-' ? $this->curUrlArray['class'] : '';
-        $this->setTitle = $this->curUrlArray['title'] != '-' ? $this->curUrlArray['title'] : '';
-        $this->setParams = $this->curUrlArray['params'] != '-' ? $this->curUrlArray['params'] : '';
-    }
-
-    /**
-     * Get the RTE configuration from Page TSConfig
-     *
-     * @return array[] RTE configuration array
-     */
-    protected function getRTEConfig()
-    {
-        $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
-        $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
-        $RTEsetup['properties']['default.'] = BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
-        return $RTEsetup['properties'];
-    }
-
-    /**
-     * Generate JS code to be used on the link insert/modify dialogue
-     *
-     * @return string the generated JS code
-     */
-    public function getJsCode()
-    {
-        // BEGIN accumulation of header JavaScript:
-        $JScode = '
-                       // This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well...
-                       var add_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . ';
-                       var add_target=' . GeneralUtility::quoteJSvalue($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . ';
-                       var add_class=' . GeneralUtility::quoteJSvalue($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . ';
-                       var add_title=' . GeneralUtility::quoteJSvalue($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . ';
-                       var add_params=' . GeneralUtility::quoteJSvalue($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . ';
-
-                       var cur_href=' . GeneralUtility::quoteJSvalue($this->curUrlArray['href'] ?: '') . ';
-                       var cur_target=' . GeneralUtility::quoteJSvalue($this->setTarget ?: '') . ';
-                       var cur_class=' . GeneralUtility::quoteJSvalue($this->setClass ?: '') . ';
-                       var cur_title=' . GeneralUtility::quoteJSvalue($this->setTitle ?: '') . ';
-                       var cur_params=' . GeneralUtility::quoteJSvalue($this->setParams ?: '') . ';
-
-                       function browse_links_setTarget(target) {
-                               cur_target=target;
-                               add_target="&curUrl[target]="+encodeURIComponent(target);
-                       }
-                       function browse_links_setClass(cssClass) {
-                               cur_class = cssClass;
-                               add_class = "&curUrl[class]="+encodeURIComponent(cssClass);
-                       }
-                       function browse_links_setTitle(title) {
-                               cur_title=title;
-                               add_title="&curUrl[title]="+encodeURIComponent(title);
-                       }
-                       function browse_links_setValue(value) {
-                               cur_href=value;
-                               add_href="&curUrl[href]="+value;
-                       }
-                       function browse_links_setParams(params) {
-                               cur_params=params;
-                               add_params="&curUrl[params]="+encodeURIComponent(params);
-                       }
-               ' . $this->doc->redirectUrls();
-
-        // Functions used, if the link selector is in wizard mode (= TCEforms fields)
-        $addPassOnParams = '';
-        if ($this->mode === 'rte') {
-            // Rich Text Editor specific configuration
-            $addPassOnParams .= '&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams);
-        }
-        $update = '';
-        if ($this->mode === 'wizard') {
-            if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(true)) {
-                $this->P['fieldChangeFunc'] = array();
-            }
-            unset($this->P['fieldChangeFunc']['alert']);
-            foreach ($this->P['fieldChangeFunc'] as $v) {
-                $update .= '
-                               window.opener.' . $v;
-            }
-            $P2 = array();
-            $P2['uid'] = $this->P['uid'];
-            $P2['pid'] = $this->P['pid'];
-            $P2['itemName'] = $this->P['itemName'];
-            $P2['formName'] = $this->P['formName'];
-            $P2['fieldChangeFunc'] = $this->P['fieldChangeFunc'];
-            $P2['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->P['fieldChangeFunc']));
-            $P2['params']['allowedExtensions'] = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : '';
-            $P2['params']['blindLinkOptions'] = isset($this->P['params']['blindLinkOptions']) ? $this->P['params']['blindLinkOptions'] : '';
-            $P2['params']['blindLinkFields'] = isset($this->P['params']['blindLinkFields']) ? $this->P['params']['blindLinkFields']: '';
-            $addPassOnParams .= GeneralUtility::implodeArrayForUrl('P', $P2);
-            $JScode .= '
-                               function link_typo3Page(id,anchor) {    //
-                                       updateValueInMainForm(id + (anchor ? anchor : ""));
-                                       close();
-                                       return false;
-                               }
-                               function link_folder(folder) {  //
-                                       updateValueInMainForm(folder);
-                                       close();
-                                       return false;
-                               }
-                               function link_current() {       //
-                                       if (cur_href!="http://" && cur_href!="mailto:") {
-                                               returnBeforeCleaned = cur_href;
-                                               if (returnBeforeCleaned.substr(0, 7) == "http://") {
-                                                       returnToMainFormValue = returnBeforeCleaned.substr(7);
-                                               } else if (returnBeforeCleaned.substr(0, 7) == "mailto:") {
-                                                       if (returnBeforeCleaned.substr(0, 14) == "mailto:mailto:") {
-                                                               returnToMainFormValue = returnBeforeCleaned.substr(14);
-                                                       } else {
-                                                               returnToMainFormValue = returnBeforeCleaned.substr(7);
-                                                       }
-                                               } else {
-                                                       returnToMainFormValue = returnBeforeCleaned;
-                                               }
-                                               updateValueInMainForm(returnToMainFormValue);
-                                               close();
-                                       }
-                                       return false;
-                               }
-                               function checkReference() {     //
-                                       if (window.opener && window.opener.document && window.opener.document.querySelector(\'form[name="'
-                        . $this->P['formName'] . '"] [data-formengine-input-name="' . $this->P['itemName'] . '"]\')) {
-                                               return window.opener.document.querySelector(\'form[name="' . $this->P['formName'] . '"] [data-formengine-input-name="' . $this->P['itemName'] . '"]\');
-                                       } else {
-                                               close();
-                                       }
-                               }
-                               function updateValueInMainForm(input) { //
-                                       var field = checkReference();
-                                       if (field) {
-                                               if (cur_target == "" && (cur_class != "" || cur_title != "" || cur_params != "")) {
-                                                       cur_target = "-";
-                                               }
-                                               if (cur_class == "" && (cur_title != "" || cur_params != "")) {
-                                                       cur_class = "-";
-                                               }
-                                               cur_class = cur_class.replace(/[\'\\"]/g, "");
-                                               if (cur_class.indexOf(" ") != -1) {
-                                                       cur_class = "\\"" + cur_class + "\\"";
-                                               }
-                                               if (cur_title == "" && cur_params != "") {
-                                                       cur_title = "-";
-                                               }
-                                               // replace each \ with \\
-                                               cur_title = cur_title.replace(/\\\\/g, "\\\\\\\\");
-                                               // replace each " with \"
-                                               cur_title = cur_title.replace(/\\"/g, "\\\\\\"");
-                                               if (cur_title.indexOf(" ") != -1) {
-                                                       cur_title = "\\"" + cur_title + "\\"";
-                                               }
-                                               if (cur_params) {
-                                                       cur_params = cur_params.replace(/\\bid\\=.*?(\\&|$)/, "");
-                                               }
-                                               input = input + " " + cur_target + " " + cur_class + " " + cur_title + " " + cur_params;
-                                               input = input.replace(/^\s+|\s+$/g, "");
-                                               if(field.value && field.className.search(/textarea/) != -1) {
-                                                       field.value += "\\n" + input;
-                                               } else {
-                                                       field.value = input;
-                                               }
-                                               if (typeof field.onchange === \'function\') {
-                                                       field.onchange();
-                                               }
-                                               ' . $update . '
-                                       }
-                               }
-                       ';
-        }
-        // General "jumpToUrl" function:
-        $JScode .= '
-                       function jumpToUrl(URL,anchor) {        //
-                               if (URL.charAt(0) === \'?\') {
-                                       URL = ' . GeneralUtility::quoteJSvalue($this->getThisScript()) . ' + URL.substring(1);
-                               }
-                               var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
-                               var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
-                               window.location.href = URL + add_act + add_mode + add_href + add_target + add_class + add_title + add_params'
-                    . ($addPassOnParams ? '+' . GeneralUtility::quoteJSvalue($addPassOnParams) : '')
-                    . '+(typeof(anchor) === "string" ? anchor : "");
-                               return false;
-                       }
-               ';
-
-        $JScode .= $this->getBParamJSCode();
-
-        // extends JavaScript code
-        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendJScode'])
-            && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendJScode'])
-        ) {
-            $_params = array(
-                'conf' => [],
-                'wizardUpdate' => $update,
-                'addPassOnParams' => $addPassOnParams
-            );
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['extendJScode'] as $objRef) {
-                $processor =& GeneralUtility::getUserObj($objRef);
-                $JScode .= $processor->extendJScode($_params, $this);
-            }
-        }
-        return $JScode;
-    }
-
-    /**
-     * Splits parts of $this->bparams and returns needed JS
-     *
-     * @return string JavaScript code
-     */
-    protected function getBParamJSCode()
-    {
-        $pArr = explode('|', $this->bparams);
-        // This is JavaScript especially for the TBE Element Browser!
-        $formFieldName = 'data[' . $pArr[0] . '][' . $pArr[1] . '][' . $pArr[2] . ']';
-        // insertElement - Call check function (e.g. for uniqueness handling):
-        $JScodeCheck = '';
-        if ($pArr[4] && $pArr[5]) {
-            $JScodeCheck = '
-                                       // Call a check function in the opener window (e.g. for uniqueness handling):
-                               if (parent.window.opener) {
-                                       var res = parent.window.opener.' . $pArr[5] . '("' . addslashes($pArr[4]) . '",table,uid,type);
-                                       if (!res.passed) {
-                                               if (res.message) alert(res.message);
-                                               performAction = false;
-                                       }
-                               } else {
-                                       alert("Error - reference to main window is not set properly!");
-                                       parent.close();
-                               }
-                       ';
-        }
-        // insertElement - Call helper function:
-        $JScodeHelper = '';
-        if ($pArr[4] && $pArr[6]) {
-            $JScodeHelper = '
-                                               // Call helper function to manage data in the opener window:
-                                       if (parent.window.opener) {
-                                               parent.window.opener.' . $pArr[6] . '("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '");
-                                       } else {
-                                               alert("Error - reference to main window is not set properly!");
-                                               parent.close();
-                                       }
-                       ';
-        }
-        // insertElement - perform action commands:
-        $JScodeActionMultiple = '';
-        if ($pArr[4] && $pArr[7]) {
-            // Call user defined action function:
-            $JScodeAction = '
-                                       if (parent.window.opener) {
-                                               parent.window.opener.' . $pArr[7] . '("' . addslashes($pArr[4]) . '",table,uid,type);
-                                               if (close) { focusOpenerAndClose(close); }
-                                       } else {
-                                               alert("Error - reference to main window is not set properly!");
-                                               if (close) { parent.close(); }
-                                       }
-                       ';
-            $JScodeActionMultiple = '
-                                               // Call helper function to manage data in the opener window:
-                                       if (parent.window.opener) {
-                                               parent.window.opener.' . $pArr[7] . 'Multiple("' . addslashes($pArr[4]) . '",table,uid,type,"'
-                . addslashes($pArr[0]) . '");
-                                       } else {
-                                               alert("Error - reference to main window is not set properly!");
-                                               parent.close();
-                                       }
-                       ';
-        } elseif ($pArr[0] && !$pArr[1] && !$pArr[2]) {
-            $JScodeAction = '
-                                       addElement(filename,table+"_"+uid,fp,close);
-                       ';
-        } else {
-            $JScodeAction = '
-                                       if (setReferences()) {
-                                               parent.window.opener.group_change("add","' . $pArr[0] . '","' . $pArr[1] . '","' . $pArr[2]
-                . '",elRef,targetDoc);
-                                       } else {
-                                               alert("Error - reference to main window is not set properly!");
-                                       }
-                                       focusOpenerAndClose(close);
-                       ';
-        }
-        return '
-                       var elRef="";
-                       var targetDoc="";
-
-                       function setReferences() {      //
-                               if (parent.window.opener && parent.window.opener.content && parent.window.opener.content.document.editform'
-            . '&& parent.window.opener.content.document.editform["' . $formFieldName . '"]) {
-                                       targetDoc = parent.window.opener.content.document;
-                                       elRef = targetDoc.editform["' . $formFieldName . '"];
-                                       return true;
-                               } else {
-                                       return false;
-                               }
-                       }
-                       function insertElement(table, uid, type, filename, fp, filetype, imagefile, action, close) {    //
-                               var performAction = true;
-                               ' . $JScodeCheck . '
-                                       // Call performing function and finish this action:
-                               if (performAction) {
-                                               ' . $JScodeHelper . $JScodeAction . '
-                               }
-                               return false;
-                       }
-                       var _hasActionMultipleCode = ' . (!empty($JScodeActionMultiple) ? 'true' : 'false') . ';
-                       function insertMultiple(table, uid) {
-                               var type = "";
-                                               ' . $JScodeActionMultiple . '
-                               return false;
-                       }
-                       function addElement(elName, elValue, altElValue, close) {       //
-                               if (parent.window.opener && parent.window.opener.setFormValueFromBrowseWin) {
-                                       parent.window.opener.setFormValueFromBrowseWin("' . $pArr[0] . '",altElValue?altElValue:elValue,elName);
-                                       focusOpenerAndClose(close);
-                               } else {
-                                       alert("Error - reference to main window is not set properly!");
-                                       parent.close();
-                               }
-                       }
-                       function focusOpenerAndClose(close) {   //
-                               BrowseLinks.focusOpenerAndClose(close);
-                       }
-               ';
-    }
-
-    /**
-     * Session data for this class can be set from outside with this method.
-     * Call after init()
-     *
-     * @param mixed[] $data Session data array
-     * @return array[] Session data and boolean which indicates that data needs to be stored in session because it's changed
-     */
-    public function processSessionData($data)
-    {
-        $store = false;
-        switch ($this->mode) {
-            case 'db':
-                if (isset($this->expandPage)) {
-                    $data['expandPage'] = $this->expandPage;
-                    $store = true;
-                } else {
-                    $this->expandPage = $data['expandPage'];
-                }
-                break;
-            case 'file':
-            case 'filedrag':
-            case 'folder':
-                if (isset($this->expandFolder)) {
-                    $data['expandFolder'] = $this->expandFolder;
-                    $store = true;
-                } else {
-                    $this->expandFolder = $data['expandFolder'];
-                }
-                break;
-            default:
-                // intentionally empty
-        }
-        return array($data, $store);
-    }
-
-    /******************************************************************
-     *
-     * Main functions
-     *
-     ******************************************************************/
-
-    /**
-     * Main entry point
-     *
-     * @return string HTML output
-     */
-    public function render()
-    {
-        // Output the correct content according to $this->mode
-        switch ($this->mode) {
-            case 'rte':
-                return $this->main_rte();
-            case 'db':
-                return $this->main_db();
-            case 'file':
-            case 'filedrag':
-                return $this->main_file();
-            case 'folder':
-                return $this->main_folder();
-            case 'wizard':
-                return $this->main_rte(true);
-        }
-        return '';
-    }
-
-    /**
-     * Rich Text Editor (RTE) link selector (MAIN function)
-     * Generates the link selector for the Rich Text Editor.
-     * Can also be used to select links for the TCEforms (see $wiz)
-     *
-     * @param bool $wiz If set, the "remove link" is not shown in the menu: Used for the "Select link" wizard which is used by the TCEforms
-     * @return string Modified content variable.
-     */
-    protected function main_rte($wiz = false)
-    {
-        // needs to be executed before doc->startPage()
-        if (in_array($this->act, array('file', 'folder'))) {
-            $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "sc_alt_file_navframe_expandtoggle"');
-        } elseif ($this->act === 'page') {
-            $this->doc->getDragDropCode('pages');
-        }
-        // Starting content:
-        $content = $this->doc->startPage('RTE link');
-        // Add the FlashMessages if any
-        $content .= $this->doc->getFlashMessages();
-
-        $content .= $this->doc->getTabMenuRaw($this->buildMenuArray($wiz, $this->getAllowedItems('page,file,folder,url,mail')));
-        // Adding the menu and header to the top of page:
-        $content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '<br />';
-        // Depending on the current action we will create the actual module content for selecting a link:
-        switch ($this->act) {
-            case 'mail':
-                $content .= $this->getEmailSelectorHtml();
-                break;
-            case 'url':
-                $content .= $this->getExternalUrlSelectorHtml();
-                break;
-            case 'file':
-            case 'folder':
-                $content .= $this->getFileSelectorHtml();
-                break;
-            case 'page':
-                $content .= $this->getPageSelectorHtml();
-                break;
-            default:
-                // Call hook
-                foreach ($this->hookObjects as $hookObject) {
-                    $content .= $hookObject->getTab($this->act);
-                }
-        }
-        $lang = $this->getLanguageService();
-
-        // Removing link fields if configured
-        $blindLinkFields = isset($this->RTEProperties['default.']['blindLinkFields'])
-            ? GeneralUtility::trimExplode(',', $this->RTEProperties['default.']['blindLinkFields'], true)
-            : array();
-        $pBlindLinkFields = isset($this->P['params']['blindLinkFields'])
-            ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkFields'], true)
-            : array();
-        $allowedFields = array_diff(array('target', 'title', 'class', 'params'), $blindLinkFields, $pBlindLinkFields);
-
-        if (in_array('params', $allowedFields, true) && $this->act !== 'url') {
-            $content .= '
-                               <!--
-                                       Selecting params for link:
-                               -->
-                               <form action="" name="lparamsform" id="lparamsform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('params', true) . '</td>
-                                                       <td><input type="text" name="lparams" class="typo3-link-input" onchange="'
-                                . 'browse_links_setParams(this.value);" value="' . htmlspecialchars($this->setParams)
-                                . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-        }
-        if (in_array('class', $allowedFields, true)) {
-            $content .= '
-                               <!--
-                                       Selecting class for link:
-                               -->
-                               <form action="" name="lclassform" id="lclassform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('class', true) . '</td>
-                                                       <td><input type="text" name="lclass" class="typo3-link-input" onchange="'
-                                . 'browse_links_setClass(this.value);" value="' . htmlspecialchars($this->setClass)
-                                . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-        }
-        if (in_array('title', $allowedFields, true)) {
-            $content .= '
-                               <!--
-                                       Selecting title for link:
-                               -->
-                               <form action="" name="ltitleform" id="ltitleform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('title', true) . '</td>
-                                                       <td><input type="text" name="ltitle" class="typo3-link-input" onchange="'
-                                . 'browse_links_setTitle(this.value);" value="' . htmlspecialchars($this->setTitle)
-                                . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-        }
-        // additional fields for page links
-        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addFields_PageLink'])
-            && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addFields_PageLink'])
-        ) {
-            $conf = array();
-            $_params = array(
-                'conf' => &$conf
-            );
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addFields_PageLink'] as $objRef) {
-                $processor =& GeneralUtility::getUserObj($objRef);
-                $content .= $processor->addFields($_params, $this);
-            }
-        }
-        // Target:
-        if ($this->act !== 'mail' && in_array('target', $allowedFields, true)) {
-            $ltarget = '
-
-                       <!--
-                               Selecting target for link:
-                       -->
-                               <form action="" name="ltargetform" id="ltargetform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
-                                               <tr>
-                                                       <td>' . $lang->getLL('target', true) . ':</td>
-                                                       <td><input type="text" name="ltarget" onchange="browse_links_setTarget(this.value);" value="'
-                                . htmlspecialchars($this->setTarget) . '"' . $this->doc->formWidth(10) . ' /></td>
-                                                       <td>
-                                                               <select name="ltarget_type" onchange="browse_links_setTarget('
-                                    . 'this.options[this.selectedIndex].value);document.ltargetform.ltarget.value='
-                                    . 'this.options[this.selectedIndex].value;this.selectedIndex=0;">
-                                                                       <option></option>
-                                                                       <option value="_top">' . $lang->getLL('top', true) . '</option>
-                                                                       <option value="_blank">' . $lang->getLL('newWindow', true) . '</option>
-                                                               </select>
-                                                       </td>
-                                                       <td>';
-            if (($this->curUrlInfo['act'] === 'page' || $this->curUrlInfo['act'] === 'file' || $this->curUrlInfo['act'] === 'folder')
-                && $this->curUrlArray['href'] && $this->curUrlInfo['act'] === $this->act
-            ) {
-                $ltarget .= '
-                                                       <input class="btn btn-default" type="submit" value="' . $lang->getLL('update', true)
-                                . '" onclick="return link_current();" />';
-            }
-            $ltarget .= '              </td>
-                                               </tr>
-                                       </table>
-                               </form>';
-            // Add "target selector" box to content:
-            $content .= $ltarget;
-            // Add some space
-            $content .= '<br /><br />';
-        }
-        // End page, return content:
-        $content .= $this->doc->endPage();
-        $content = $this->doc->insertStylesAndJS($content);
-        return $content;
-    }
-
-    /**
-     * Get the allowed items or tabs
-     *
-     * @param string $items initial list of possible items
-     * @return array the allowed items
-     */
-    public function getAllowedItems($items)
-    {
-        $allowedItems = explode(',', $items);
-        // Call hook for extra options
-        foreach ($this->hookObjects as $hookObject) {
-            $allowedItems = $hookObject->addAllowedItems($allowedItems);
-        }
-
-        // Initializing the action value, possibly removing blinded values etc:
-        $blindLinkOptions = isset($this->RTEProperties['default.']['blindLinkOptions'])
-            ? GeneralUtility::trimExplode(',', $this->RTEProperties['default.']['blindLinkOptions'], true)
-            : array();
-        $pBlindLinkOptions = isset($this->P['params']['blindLinkOptions'])
-            ? GeneralUtility::trimExplode(',', $this->P['params']['blindLinkOptions'])
-            : array();
-        $allowedItems = array_diff($allowedItems, $blindLinkOptions, $pBlindLinkOptions);
-
-        reset($allowedItems);
-        if (!in_array($this->act, $allowedItems)) {
-            $this->act = current($allowedItems);
-        }
-        return $allowedItems;
-    }
-
-    /**
-     * Returns an array definition of the top menu
-     *
-     * @param bool $wiz
-     * @param array $allowedItems
-     * @return mixed[][]
-     */
-    protected function buildMenuArray($wiz, $allowedItems)
-    {
-        $lang = $this->getLanguageService();
-
-        $menuDef = array();
-        if (!$wiz && $this->curUrlArray['href']) {
-            $menuDef['removeLink']['isActive'] = $this->act === 'removeLink';
-            $menuDef['removeLink']['label'] = $lang->getLL('removeLink', true);
-            $menuDef['removeLink']['url'] = '#';
-            $menuDef['removeLink']['addParams'] = 'onclick="plugin.unLink();return false;"';
-        }
-        if (in_array('page', $allowedItems, true)) {
-            $menuDef['page']['isActive'] = $this->act === 'page';
-            $menuDef['page']['label'] = $lang->getLL('page', true);
-            $menuDef['page']['url'] = '#';
-            $menuDef['page']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=page&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
-        }
-        if (in_array('file', $allowedItems, true)) {
-            $menuDef['file']['isActive'] = $this->act === 'file';
-            $menuDef['file']['label'] = $lang->getLL('file', true);
-            $menuDef['file']['url'] = '#';
-            $menuDef['file']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=file&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
-        }
-        if (in_array('folder', $allowedItems, true)) {
-            $menuDef['folder']['isActive'] = $this->act === 'folder';
-            $menuDef['folder']['label'] = $lang->getLL('folder', true);
-            $menuDef['folder']['url'] = '#';
-            $menuDef['folder']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=folder&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
-        }
-        if (in_array('url', $allowedItems, true)) {
-            $menuDef['url']['isActive'] = $this->act === 'url';
-            $menuDef['url']['label'] = $lang->getLL('extUrl', true);
-            $menuDef['url']['url'] = '#';
-            $menuDef['url']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=url&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
-        }
-        if (in_array('mail', $allowedItems, true)) {
-            $menuDef['mail']['isActive'] = $this->act === 'mail';
-            $menuDef['mail']['label'] = $lang->getLL('email', true);
-            $menuDef['mail']['url'] = '#';
-            $menuDef['mail']['addParams'] = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?act=mail&mode=' . $this->mode . '&bparams=' . $this->bparams) . ');return false;"';
-        }
-        // Call hook for extra options
-        foreach ($this->hookObjects as $hookObject) {
-            $menuDef = $hookObject->modifyMenuDefinition($menuDef);
-        }
-        return $menuDef;
-    }
-
-    /**
-     * Returns HTML of the email link from
-     *
-     * @return string
-     */
-    protected function getEmailSelectorHtml()
-    {
-        $lang = $this->getLanguageService();
-        $extUrl = '
-                       <!--
-                               Enter mail address:
-                       -->
-                       <form action="" name="lurlform" id="lurlform">
-                               <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkMail">
-                                       <tr>
-                                               <td style="width: 96px;">
-                                                       ' . $lang->getLL('emailAddress', true) . ':
-                                               </td>
-                                               <td>
-                                                       <input type="text" name="lemail"' . $this->doc->formWidth(20) . ' value="'
-                                . htmlspecialchars(($this->curUrlInfo['act'] === 'mail' ? $this->curUrlInfo['info'] : ''))
-                                . '" />
-                                                       <input class="btn btn-default" type="submit" value="' . $lang->getLL('setLink', true)
-                                . '" onclick="browse_links_setTarget(\'\');browse_links_setValue(\'mailto:\'+'
-                                . 'document.lurlform.lemail.value); return link_current();" />
-                                               </td>
-                                       </tr>
-                               </table>
-                       </form>';
-        return $extUrl;
-    }
-
-    /**
-     * Returns HTML of the external url link from
-     *
-     * @return string
-     */
-    protected function getExternalUrlSelectorHtml()
-    {
-        $extUrl = '
-
-                               <!--
-                                       Enter External URL:
-                               -->
-                                               <form action="" name="lurlform" id="lurlform">
-                                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkURL">
-                                                               <tr>
-                                                                       <td style="width: 96px;">URL:</td>
-                                                                       <td><input type="text" name="lurl"' . $this->doc->formWidth(30) . ' value="'
-            . htmlspecialchars(($this->curUrlInfo['act'] === 'url' ? $this->curUrlInfo['info'] : 'http://'))
-            . '" /> ' . '<input class="btn btn-default" type="submit" value="' . $this->getLanguageService()->getLL('setLink', true)
-            . '" onclick="browse_links_setValue(document.lurlform.lurl.value); return link_current();" /></td>
-                                                               </tr>
-                                                       </table>
-                                               </form>';
-        return $extUrl;
-    }
-
-    /**
-     * Returns HTML of the file/folder link selector
-     *
-     * @param string $treeClassName
-     * @return string
-     */
-    protected function getFileSelectorHtml($treeClassName = ElementBrowserFolderTreeView::class)
-    {
-        /** @var ElementBrowserFolderTreeView $folderTree */
-        $folderTree = GeneralUtility::makeInstance($treeClassName);
-        $folderTree->setLinkParameterProvider($this);
-        $folderTree->thisScript = $this->thisScript;
-        $tree = $folderTree->getBrowsableTree();
-        $backendUser = $this->getBackendUser();
-        if ($this->curUrlInfo['value'] && $this->curUrlInfo['act'] === $this->act) {
-            $cmpPath = $this->curUrlInfo['value'];
-            if (!isset($this->expandFolder)) {
-                $this->expandFolder = $cmpPath;
-            }
-        }
-        // Create upload/create folder forms, if a path is given
-        $selectedFolder = false;
-        if ($this->expandFolder) {
-            $fileOrFolderObject = null;
-            try {
-                $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
-            } catch (\Exception $e) {
-                // No path is selected
-            }
-
-            if ($fileOrFolderObject instanceof Folder) {
-                // It's a folder
-                $selectedFolder = $fileOrFolderObject;
-            } elseif ($fileOrFolderObject instanceof FileInterface) {
-                // It's a file
-                try {
-                    $selectedFolder = $fileOrFolderObject->getParentFolder();
-                } catch (\Exception $e) {
-                    // Accessing the parent folder failed for some reason. e.g. permissions
-                }
-            }
-        }
-        // If no folder is selected, get the user's default upload folder
-        if (!$selectedFolder) {
-            try {
-                $selectedFolder = $backendUser->getDefaultUploadFolder();
-            } catch (\Exception $e) {
-                // The configured default user folder does not exist
-            }
-        }
-        // Build the file upload and folder creation form
-        $uploadForm = '';
-        $createFolder = '';
-        $content = '';
-        if ($selectedFolder) {
-            $uploadForm = ($this->act === 'file') ? $this->uploadForm($selectedFolder) : '';
-            $createFolder = $this->createFolder($selectedFolder);
-        }
-        // Insert the upload form on top, if so configured
-        if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
-            $content .= $uploadForm;
-        }
-
-        // Render the filelist if there is a folder selected
-        $files = '';
-        if ($selectedFolder) {
-            $allowedExtensions = isset($this->P['params']['allowedExtensions']) ? $this->P['params']['allowedExtensions'] : '';
-            $files = $this->expandFolder($selectedFolder, $allowedExtensions);
-        }
-        // Create folder tree:
-        $content .= '
-                               <!--
-                                       Wrapper table for folder tree / file/folder list:
-                               -->
-                                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkFiles">
-                                                       <tr>
-                                                               <td class="c-wCell" valign="top">'
-            . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':')) . $tree . '</td>
-                                                               <td class="c-wCell" valign="top">' . $files . '</td>
-                                                       </tr>
-                                               </table>
-                                               ';
-        // Adding create folder + upload form if applicable
-        if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
-            $content .= $uploadForm;
-        }
-        $content .=  '<br />' . $createFolder . '<br />';
-        return $content;
-    }
-
-    /**
-     * Returns HTML of the page link selector
-     *
-     * @param string $treeClassName name of the class used for page tree rendering
-     * @return string
-     */
-    protected function getPageSelectorHtml($treeClassName = ElementBrowserPageTreeView::class)
-    {
-        $backendUser = $this->getBackendUser();
-
-        /** @var ElementBrowserPageTreeView $pageTree */
-        $pageTree = GeneralUtility::makeInstance($treeClassName);
-        $pageTree->setLinkParameterProvider($this);
-        $pageTree->thisScript = $this->thisScript;
-        $pageTree->ext_showPageId = (bool)$backendUser->getTSConfigVal('options.pageTree.showPageIdWithTitle');
-        $pageTree->ext_showNavTitle = (bool)$backendUser->getTSConfigVal('options.pageTree.showNavTitle');
-        $pageTree->addField('nav_title');
-        $tree = $pageTree->getBrowsableTree();
-        $cElements = $this->expandPage();
-        $dbmount = $this->getTemporaryTreeMountCancelNotice();
-        $content = '
-
-                               <!--
-                                       Wrapper table for page tree / record list:
-                               -->
-                                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-linkPages">
-                                                       <tr>
-                                                               <td class="c-wCell" valign="top">'
-            . $this->barheader(($this->getLanguageService()->getLL('pageTree') . ':'))
-            . $dbmount
-            . $tree . '</td>
-                                                               <td class="c-wCell" valign="top">' . $cElements . '</td>
-                                                       </tr>
-                                               </table>
-                                               ';
-        return $content;
-    }
-
-    /**
-     * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for files.
-     *
-     * @return string HTML content for the module
-     */
-    protected function main_file()
-    {
-        // include JS files and set prefs for foldertree
-        $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "sc_alt_file_navframe_expandtoggle"');
-        // Starting content:
-        $content = $this->doc->startPage('TBE file selector');
-        // Add the FlashMessages if any
-        $content .= $this->doc->getFlashMessages();
-        // Init variable:
-        $pArr = explode('|', $this->bparams);
-        // The key number 3 of the pArr contains the "allowed" string. Disallowed is not passed to
-        // the element browser at all but only filtered out in TCEMain afterwards
-        $allowed = $pArr[3];
-        if ($allowed !== 'sys_file' && $allowed !== '*' && !empty($allowed)) {
-            $allowedFileExtensions = $allowed;
-        }
-        $backendUser = $this->getBackendUser();
-
-        if (isset($allowedFileExtensions)) {
-            // Create new filter object
-            $filterObject = GeneralUtility::makeInstance(FileExtensionFilter::class);
-            $filterObject->setAllowedFileExtensions($allowedFileExtensions);
-            // Set file extension filters on all storages
-            $storages = $backendUser->getFileStorages();
-            /** @var $storage \TYPO3\CMS\Core\Resource\ResourceStorage */
-            foreach ($storages as $storage) {
-                $storage->addFileAndFolderNameFilter(array($filterObject, 'filterFileList'));
-            }
-        }
-        // Create upload/create folder forms, if a path is given
-        $this->selectedFolder = false;
-        if ($this->expandFolder) {
-            $fileOrFolderObject = null;
-
-            // Try to fetch the folder the user had open the last time he browsed files
-            // Fallback to the default folder in case the last used folder is not existing
-            try {
-                $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->expandFolder);
-            } catch (Exception $accessException) {
-                // We're just catching the exception here, nothing to be done if folder does not exist or is not accessible.
-            }
-
-            if ($fileOrFolderObject instanceof Folder) {
-                // It's a folder
-                $this->selectedFolder = $fileOrFolderObject;
-            } elseif ($fileOrFolderObject instanceof FileInterface) {
-                // It's a file
-                $this->selectedFolder = $fileOrFolderObject->getParentFolder();
-            }
-        }
-        // Or get the user's default upload folder
-        if (!$this->selectedFolder) {
-            try {
-                $this->selectedFolder = $backendUser->getDefaultUploadFolder();
-            } catch (\Exception $e) {
-                // The configured default user folder does not exist
-            }
-        }
-            // Build the file upload and folder creation form
-        $uploadForm = '';
-        $createFolder = '';
-        if ($this->selectedFolder) {
-            $uploadForm = $this->uploadForm($this->selectedFolder);
-            $createFolder = $this->createFolder($this->selectedFolder);
-        }
-        // Insert the upload form on top, if so configured
-        if ($backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
-            $content .= $uploadForm;
-        }
-        // Getting flag for showing/not showing thumbnails:
-        $noThumbs = $backendUser->getTSConfigVal('options.noThumbsInEB');
-        $_MOD_SETTINGS = array();
-        if (!$noThumbs) {
-            // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
-            $_MOD_MENU = array('displayThumbs' => '');
-            $_MCONF['name'] = 'file_list';
-            $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
-        }
-        $noThumbs = $noThumbs ?: !$_MOD_SETTINGS['displayThumbs'];
-        // Create folder tree:
-        /** @var ElementBrowserFolderTreeView $folderTree */
-        $folderTree = GeneralUtility::makeInstance(ElementBrowserFolderTreeView::class);
-        $folderTree->setLinkParameterProvider($this);
-        $folderTree->thisScript = $this->thisScript;
-        $folderTree->ext_noTempRecyclerDirs = $this->mode === 'filedrag';
-        $tree = $folderTree->getBrowsableTree();
-        if ($this->selectedFolder) {
-            if ($this->mode === 'filedrag') {
-                $files = $this->TBE_dragNDrop($this->selectedFolder, $pArr[3]);
-            } else {
-                $files = $this->TBE_expandFolder($this->selectedFolder, $pArr[3], $noThumbs);
-            }
-        } else {
-            $files = '';
-        }
-
-        // Putting the parts together, side by side:
-        $content .= '
-
-                       <!--
-                               Wrapper table for folder tree / filelist:
-                       -->
-                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
-                               <tr>
-                                       <td class="c-wCell" valign="top">' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':'))
-                        . $tree . '</td>
-                                       <td class="c-wCell" valign="top">' . $files . '</td>
-                               </tr>
-                       </table>
-                       ';
-
-
-        // Adding create folder + upload forms if applicable:
-        if (!$backendUser->getTSConfigVal('options.uploadFieldsInTopOfEB')) {
-            $content .= $uploadForm;
-        }
-        $content .= $createFolder;
-        // Add some space
-        $content .= '<br /><br />';
-        // Setup indexed elements:
-        $this->doc->JScode .= $this->doc->wrapScriptTags('
-               require(["TYPO3/CMS/Recordlist/BrowseFiles"], function(BrowseLinks) {
-                       BrowseFiles.addElements(' . json_encode($this->elements) . ');
-               });');
-        // Ending page, returning content:
-        $content .= $this->doc->endPage();
-        $content = $this->doc->insertStylesAndJS($content);
-        return $content;
-    }
-
-    /**
-     * TYPO3 Element Browser: Showing a folder tree, allowing you to browse for folders.
-     *
-     * @return string HTML content for the module
-     */
-    protected function main_folder()
-    {
-        // include JS files
-        // Setting prefs for foldertree
-        $this->doc->getDragDropCode('folders', 'Tree.ajaxID = "sc_alt_file_navframe_expandtoggle";');
-        // Starting content:
-        $content = $this->doc->startPage('TBE folder selector');
-        // Add the FlashMessages if any
-        $content .= $this->doc->getFlashMessages();
-        // Init variable:
-        $parameters = explode('|', $this->bparams);
-        if ($this->expandFolder) {
-            $this->selectedFolder = ResourceFactory::getInstance()->getFolderObjectFromCombinedIdentifier($this->expandFolder);
-        }
-        if ($this->selectedFolder) {
-            $createFolder = $this->createFolder($this->selectedFolder);
-        } else {
-            $createFolder = '';
-        }
-        // Create folder tree:
-        /** @var ElementBrowserFolderTreeView $folderTree */
-        $folderTree = GeneralUtility::makeInstance(ElementBrowserFolderTreeView::class);
-        $folderTree->setLinkParameterProvider($this);
-        $folderTree->thisScript = $this->thisScript;
-        $folderTree->ext_noTempRecyclerDirs = $this->mode === 'filedrag';
-        $tree = $folderTree->getBrowsableTree();
-        $folders = '';
-        if ($this->selectedFolder) {
-            if ($this->mode === 'filedrag') {
-                $folders = $this->TBE_dragNDrop($this->selectedFolder, $parameters[3]);
-            } else {
-                $folders = $this->TBE_expandSubFolders($this->selectedFolder);
-            }
-        }
-        // Putting the parts together, side by side:
-        $content .= '
-
-                       <!--
-                               Wrapper table for folder tree / folder list:
-                       -->
-                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-EBfiles">
-                               <tr>
-                                       <td class="c-wCell" valign="top">' . $this->barheader(($this->getLanguageService()->getLL('folderTree') . ':'))
-                        . $tree . '</td>
-                                       <td class="c-wCell" valign="top">' . $folders . '</td>
-                               </tr>
-                       </table>
-                       ';
-        // Adding create folder if applicable:
-        $content .= $createFolder;
-        // Add some space
-        $content .= '<br /><br />';
-        // Ending page, returning content:
-        $content .= $this->doc->endPage();
-        $content = $this->doc->insertStylesAndJS($content);
-        return $content;
-    }
-
-    /******************************************************************
-     *
-     * Record listing
-     *
-     ******************************************************************/
-    /**
-     * For RTE: This displays all content elements on a page and lets you create a link to the element.
-     *
-     * @return string HTML output. Returns content only if the ->expandPage value is set (pointing to a page uid to show tt_content records from ...)
-     */
-    public function expandPage()
-    {
-        $out = '';
-        // Set page id (if any) to expand
-        $expPageId = $this->expandPage;
-        // If there is an anchor value (content element reference) in the element reference, then force an ID to expand:
-        if (!$this->expandPage && $this->curUrlInfo['cElement']) {
-            // Set to the current link page id.
-            $expPageId = $this->curUrlInfo['pageid'];
-        }
-        // Draw the record list IF there is a page id to expand:
-        if (
-            $expPageId
-            && MathUtility::canBeInterpretedAsInteger($expPageId)
-            && $this->getBackendUser()->isInWebMount($expPageId)
-        ) {
-            // Set header:
-            $out .= $this->barheader($this->getLanguageService()->getLL('contentElements') . ':');
-            // Create header for listing, showing the page title/icon:
-            $mainPageRec = BackendUtility::getRecordWSOL('pages', $expPageId);
-            $db = $this->getDatabaseConnection();
-            $out .= '
-                               <ul class="list-tree list-tree-root list-tree-root-clean">
-                                       <li class="list-tree-control-open">
-                                               <span class="list-tree-group">
-                                                       <span class="list-tree-icon">' . $this->iconFactory->getIconForRecord('pages', $mainPageRec, Icon::SIZE_SMALL)->render() . '</span>
-                                                       <span class="list-tree-title">' . htmlspecialchars(BackendUtility::getRecordTitle('pages', $mainPageRec, true)) . '</span>
-                                               </span>
-                                               <ul>
-                               ';
-
-            // Look up tt_content elements from the expanded page:
-            $res = $db->exec_SELECTquery(
-                'uid,header,hidden,starttime,endtime,fe_group,CType,colPos,bodytext',
-                'tt_content',
-                'pid=' . (int)$expPageId . BackendUtility::deleteClause('tt_content')
-                    . BackendUtility::versioningPlaceholderClause('tt_content'),
-                '',
-                'colPos,sorting'
-            );
-            // Traverse list of records:
-            $c = 0;
-            while ($row = $db->sql_fetch_assoc($res)) {
-                $c++;
-                $icon = $this->iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render();
-                $selected = '';
-                if ($this->curUrlInfo['act'] == 'page' && $this->curUrlInfo['cElement'] == $row['uid']) {
-                    $selected = ' class="active"';
-                }
-                // Putting list element HTML together:
-                $out .= '
-                                       <li' . $selected . '>
-                                               <span class="list-tree-group">
-                                                       <span class="list-tree-icon">
-                                                               ' . $icon . '
-                                                       </span>
-                                                       <span class="list-tree-title">
-                                                               <a href="#" onclick="return link_typo3Page(\'' . $expPageId . '\',\'#' . $row['uid'] . '\');">
-                                                                       ' . htmlspecialchars(BackendUtility::getRecordTitle('tt_content', $row, true)) . '
-                                                               </a>
-                                                       </span>
-                                               </span>
-                                       </li>
-                                       ';
-            }
-            $out .= '
-                                               </ul>
-                                       </li>
-                               </ul>
-                               ';
-        }
-        return $out;
-    }
-
-    /**
-     * For TYPO3 Element Browser: This lists all content elements from the given list of tables
-     *
-     * @param string $tables Comma separated list of tables. Set to "*" if you want all tables.
-     * @return string HTML output.
-     */
-    public function TBE_expandPage($tables)
-    {
-        $backendUser = $this->getBackendUser();
-        if (!MathUtility::canBeInterpretedAsInteger($this->expandPage)
-            || $this->expandPage < 0
-            || !$backendUser->isInWebMount($this->expandPage)
-        ) {
-            return '';
-        }
-        // Set array with table names to list:
-        if (trim($tables) === '*') {
-            $tablesArr = array_keys($GLOBALS['TCA']);
-        } else {
-            $tablesArr = GeneralUtility::trimExplode(',', $tables, true);
-        }
-        reset($tablesArr);
-        // Headline for selecting records:
-        $out = $this->barheader($this->getLanguageService()->getLL('selectRecords') . ':');
-        // Create the header, showing the current page for which the listing is.
-        // Includes link to the page itself, if pages are amount allowed tables.
-        $titleLen = (int)$backendUser->uc['titleLen'];
-        $mainPageRec = BackendUtility::getRecordWSOL('pages', $this->expandPage);
-        $ATag = '';
-        $ATag_e = '';
-        $ATag2 = '';
-        $picon = '';
-        if (is_array($mainPageRec)) {
-            $picon = $this->iconFactory->getIconForRecord('pages', $mainPageRec, Icon::SIZE_SMALL)->render();
-            if (in_array('pages', $tablesArr)) {
-                $ATag = '<a href="#" onclick="return insertElement(\'pages\', \'' . $mainPageRec['uid'] . '\', \'db\', '
-                    . GeneralUtility::quoteJSvalue($mainPageRec['title']) . ', \'\', \'\', \'\',\'\',1);">';
-                $ATag2 = '<a href="#" onclick="return insertElement(\'pages\', \'' . $mainPageRec['uid'] . '\', \'db\', '
-                    . GeneralUtility::quoteJSvalue($mainPageRec['title']) . ', \'\', \'\', \'\',\'\',0);">';
-                $ATag_e = '</a>';
-            }
-        }
-        $pBicon = $ATag2 ? $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() : '';
-        $pText = htmlspecialchars(GeneralUtility::fixed_lgd_cs($mainPageRec['title'], $titleLen));
-        $out .= $picon . $ATag2 . $pBicon . $ATag_e . $ATag . $pText . $ATag_e . '<br />';
-        // Initialize the record listing:
-        $id = $this->expandPage;
-        $pointer = MathUtility::forceIntegerInRange($this->pointer, 0, 100000);
-        $perms_clause = $backendUser->getPagePermsClause(1);
-        $pageInfo = BackendUtility::readPageAccess($id, $perms_clause);
-        // Generate the record list:
-        /** @var $dbList ElementBrowserRecordList */
-        if (is_object($this->recordList)) {
-            $dbList = $this->recordList;
-        } else {
-            $dbList = GeneralUtility::makeInstance(ElementBrowserRecordList::class);
-        }
-        $dbList->setElementBrowser($this);
-        $dbList->thisScript = $this->thisScript;
-        $dbList->thumbs = 0;
-        $dbList->localizationView = 1;
-        $dbList->setIsEditable(false);
-        $dbList->calcPerms = $backendUser->calcPerms($pageInfo);
-        $dbList->noControlPanels = 1;
-        $dbList->clickMenuEnabled = 0;
-        $dbList->tableList = implode(',', $tablesArr);
-        $pArr = explode('|', $this->bparams);
-        // a string like "data[pages][79][storage_pid]"
-        $fieldPointerString = $pArr[0];
-        // parts like: data, pages], 79], storage_pid]
-        $fieldPointerParts = explode('[', $fieldPointerString);
-        $relatingTableName = substr($fieldPointerParts[1], 0, -1);
-        $relatingFieldName = substr($fieldPointerParts[3], 0, -1);
-        if ($relatingTableName && $relatingFieldName) {
-            $dbList->setRelatingTableAndField($relatingTableName, $relatingFieldName);
-        }
-        $dbList->start($id, GeneralUtility::_GP('table'), $pointer, GeneralUtility::_GP('search_field'),
-            GeneralUtility::_GP('search_levels'), GeneralUtility::_GP('showLimit')
-        );
-        $dbList->setDispFields();
-        $dbList->generateList();
-        $out .= $dbList->getSearchBox();
-        $out .= "<script>document.getElementById('db_list-searchbox-toolbar').style.display = 'block';document.getElementById('db_list-searchbox-toolbar').style.position = 'relative';</script>";
-
-        //     Add the HTML for the record list to output variable:
-        $out .= $dbList->HTMLcode;
-        // Add support for fieldselectbox in singleTableMode
-        if ($dbList->table) {
-            $out .= $dbList->fieldSelectBox($dbList->table);
-        }
-
-        // Return accumulated content:
-        return $out;
-    }
-
-    /**
-     * Render list of folders inside a folder.
-     *
-     * @param Folder $folder Folder
-     * @return string HTML output
-     */
-    public function TBE_expandSubFolders(Folder $folder)
-    {
-        $content = '';
-        if ($folder->checkActionPermission('read')) {
-            $content .= $this->folderList($folder);
-        }
-        // Return accumulated content for folderlisting:
-        return $content;
-    }
-
-    /******************************************************************
-     *
-     * Filelisting
-     *
-     ******************************************************************/
-    /**
-     * For RTE: This displays all files from folder. No thumbnails shown
-     *
-     * @param Folder $folder The folder path to expand
-     * @param string $extensionList List of file extensions to show
-     * @return string HTML output
-     */
-    public function expandFolder(Folder $folder, $extensionList = '')
-    {
-        if (!$folder->checkActionPermission('read')) {
-            return '';
-        }
-        $lang = $this->getLanguageService();
-        $renderFolders = $this->act === 'folder';
-        // Create header for file/folder listing:
-        if ($renderFolders) {
-            $out = $this->barheader($lang->getLL('folders') . ':');
-        } else {
-            $out = $this->barheader($lang->getLL('files') . ':');
-        }
-        // Prepare current path value for comparison (showing red arrow)
-        $currentIdentifier = '';
-        if ($this->curUrlInfo['value']) {
-            $currentIdentifier = $this->curUrlInfo['info'];
-        }
-        // Create header element; The folder from which files are listed.
-        $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
-        $folderIcon = $this->iconFactory->getIconForResource($folder, Icon::SIZE_SMALL)->render();
-        $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen));
-        $selected = '';
-        if ($this->curUrlInfo['act'] == 'folder' && $currentIdentifier == $folder->getCombinedIdentifier()) {
-            $selected = ' class="bg-success"';
-        }
-        $out .= '
-                       <a href="#"' . $selected . ' title="' . htmlspecialchars($folder->getIdentifier()) . '" onclick="return link_folder(\'file:' . $folder->getCombinedIdentifier() . '\');">
-                               ' . $folderIcon . '
-                       </a>
-                       ';
-        // Get files from the folder:
-        if ($renderFolders) {
-            $items = $folder->getSubfolders();
-        } else {
-            $items = $this->getFilesInFolder($folder, $extensionList);
-        }
-        $c = 0;
-
-        if (!empty($items)) {
-            $out .= '<ul class="list-tree list-tree-root">';
-            foreach ($items as $fileOrFolderObject) {
-                $c++;
-                if ($renderFolders) {
-                    $fileIdentifier = $fileOrFolderObject->getCombinedIdentifier();
-                    $overlay = null;
-                    if ($fileOrFolderObject instanceof InaccessibleFolder) {
-                        $overlay = array('status-overlay-locked' => array());
-                    }
-                    $icon = '<span title="' . htmlspecialchars($fileOrFolderObject->getName()) . '">'
-                        . $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL, $overlay)->render()
-                        . '</span>';
-                    $itemUid = 'file:' . $fileIdentifier;
-                } else {
-                    $fileIdentifier = $fileOrFolderObject->getUid();
-                    // Get size and icon:
-                    $size = ' (' . GeneralUtility::formatSize($fileOrFolderObject->getSize()) . 'bytes)';
-                    $icon = '<span title="' . htmlspecialchars($fileOrFolderObject->getName() . $size) . '">' . $this->iconFactory->getIconForResource($fileOrFolderObject, Icon::SIZE_SMALL)->render() . '</span>';
-                    $itemUid = 'file:' . $fileIdentifier;
-                }
-                $selected = '';
-                if (($this->curUrlInfo['act'] == 'file' || $this->curUrlInfo['act'] == 'folder')
-                    && $currentIdentifier == $fileIdentifier
-                ) {
-                    $selected = ' class="active"';
-                }
-                // Put it all together for the file element:
-                $out .=
-                    '<li' . $selected . '>
-                                               <a href="#"title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" onclick="return link_folder(\'' . $itemUid . '\');">
-                                                       ' .    $icon . '
-                                                       ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) . '
-                                               </a>
-                                       </li>';
-            }
-            $out .= '</ul>';
-        }
-        return $out;
-    }
-
-    /**
-     * For TYPO3 Element Browser: Expand folder of files.
-     *
-     * @param Folder $folder The folder path to expand
-     * @param string $extensionList List of fileextensions to show
-     * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown.
-     * @return string HTML output
-     */
-    public function TBE_expandFolder(Folder $folder, $extensionList = '', $noThumbs = false)
-    {
-        if (!$folder->checkActionPermission('read')) {
-            return '';
-        }
-        $extensionList = $extensionList == '*' ? '' : $extensionList;
-        if ($this->searchWord !== '') {
-            $files = $this->fileRepository->searchByName($folder, $this->searchWord);
-        } else {
-            $files = $this->getFilesInFolder($folder, $extensionList);
-        }
-
-        return $this->fileList($files, $folder, $noThumbs);
-    }
-
-    /**
-     * Render list of files.
-     *
-     * @param File[] $files List of files
-     * @param Folder $folder If set a header with a folder icon and folder name are shown
-     * @param bool $noThumbs Whether to show thumbnails or not. If set, no thumbnails are shown.
-     * @return string HTML output
-     */
-    protected function fileList(array $files, Folder $folder = null, $noThumbs = false)
-    {
-        $out = '';
-
-        $lang = $this->getLanguageService();
-        $lines = array();
-        // Create headline (showing number of files):
-        $filesCount = count($files);
-        $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', $filesCount));
-        $out .= $this->getFileSearchField();
-        $out .= '<div id="filelist">';
-        $out .= $this->getBulkSelector($filesCount);
-        $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
-        // Create the header of current folder:
-        if ($folder) {
-            $folderIcon = $this->iconFactory->getIconForResource($folder, Icon::SIZE_SMALL);
-            $lines[] = '<tr class="t3-row-header">
-                               <td colspan="4">' . $folderIcon->render()
-                . htmlspecialchars(GeneralUtility::fixed_lgd_cs($folder->getIdentifier(), $titleLen)) . '</td>
-                       </tr>';
-        }
-        if ($filesCount == 0) {
-            $lines[] = '
-                               <tr class="file_list_normal">
-                                       <td colspan="4">No files found.</td>
-                               </tr>';
-        }
-        // Traverse the filelist:
-        /** @var $fileObject File */
-        foreach ($files as $fileObject) {
-            $fileExtension = $fileObject->getExtension();
-            // Thumbnail/size generation:
-            $imgInfo = array();
-            if (GeneralUtility::inList(strtolower($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] . ',' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['mediafile_ext']), strtolower($fileExtension)) && !$noThumbs) {
-                $processedFile = $fileObject->process(
-                    ProcessedFile::CONTEXT_IMAGEPREVIEW,
-                    array('width' => 64, 'height' => 64)
-                );
-                $imageUrl = $processedFile->getPublicUrl(true);
-                $imgInfo = array(
-                    $fileObject->getProperty('width'),
-                    $fileObject->getProperty('height')
-                );
-                $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels';
-                $clickIcon = '<img src="' . $imageUrl . '" ' .
-                            'width="' . $processedFile->getProperty('width') . '" ' .
-                            'height="' . $processedFile->getProperty('height') . '" ' .
-                            'hspace="5" vspace="5" border="1" />';
-            } else {
-                $clickIcon = '';
-                $pDim = '';
-            }
-            // Create file icon:
-            $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')';
-            $icon = '<span title="' . htmlspecialchars($fileObject->getName() . $size) . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>';
-            // Create links for adding the file:
-            $filesIndex = count($this->elements);
-            $this->elements['file_' . $filesIndex] = array(
-                'type' => 'file',
-                'table' => 'sys_file',
-                'uid' => $fileObject->getUid(),
-                'fileName' => $fileObject->getName(),
-                'filePath' => $fileObject->getUid(),
-                'fileExt' => $fileExtension,
-                'fileIcon' => $icon
-            );
-            if ($this->fileIsSelectableInFileList($fileObject, $imgInfo)) {
-                $ATag = '<a href="#" title="' . htmlspecialchars($fileObject->getName()) . '" onclick="return BrowseLinks.File.insertElement(\'file_' . $filesIndex . '\');">';
-                $ATag_alt = substr($ATag, 0, -4) . ',1);">';
-                $bulkCheckBox = '<input type="checkbox" class="typo3-bulk-item" name="file_' . $filesIndex . '" value="0" /> ';
-                $ATag_e = '</a>';
-            } else {
-                $ATag = '';
-                $ATag_alt = '';
-                $ATag_e = '';
-                $bulkCheckBox = '';
-            }
-            // Create link to showing details about the file in a window:
-            $Ahref = BackendUtility::getModuleUrl('show_item', array(
-                'type' => 'file',
-                'table' => '_FILE',
-                'uid' => $fileObject->getCombinedIdentifier(),
-                'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
-            ));
-            $ATag2_e = '</a>';
-            // Combine the stuff:
-            $filenameAndIcon = $bulkCheckBox . $ATag_alt . $icon
-                . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(), $titleLen)) . $ATag_e;
-            // Show element:
-            if ($pDim) {
-                // Image...
-                $lines[] = '
-                                       <tr class="file_list_normal">
-                                               <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
-                                               <td>' . $ATag . '<span title="' .  $lang->getLL('addToList', true) . '">' . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . '</span>' . $ATag_e . '</td>
-                                               <td nowrap="nowrap"><a href="' . htmlspecialchars($Ahref) . '" title="' . $lang->getLL('info', true) . '">' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . $lang->getLL('info', true) . $ATag2_e . '</td>
-                                               <td nowrap="nowrap">&nbsp;' . $pDim . '</td>
-                                       </tr>';
-                $lines[] = '
-                                       <tr>
-                                               <td class="filelistThumbnail" colspan="4">' . $ATag_alt . $clickIcon . $ATag_e . '</td>
-                                       </tr>';
-            } else {
-                $lines[] = '
-                                       <tr class="file_list_normal">
-                                               <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
-                                               <td>' . $ATag . '<span title="' . $lang->getLL('addToList', true) . '">' . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . '</span>' . $ATag_e . '</td>
-                                               <td nowrap="nowrap"><a href="' . htmlspecialchars($Ahref) . '" title="' . $lang->getLL('info', true) . '">' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . $lang->getLL('info', true) . $ATag2_e . '</td>
-                                               <td>&nbsp;</td>
-                                       </tr>';
-            }
-        }
-        // Wrap all the rows in table tags:
-        $out .= '
-
-       <!--
-               Filelisting
-       -->
-                       <table cellpadding="0" cellspacing="0" id="typo3-filelist">
-                               ' . implode('', $lines) . '
-                       </table>';
-        // Return accumulated content for filelisting:
-        $out .= '</div>';
-        return $out;
-    }
-
-    /**
-     * Checks if the given file is selectable in the filelist.
-     *
-     * By default all files are selectable. This method may be overwritten in child classes.
-     *
-     * @param FileInterface $file
-     * @param mixed[] $imgInfo Image dimensions from \TYPO3\CMS\Core\Imaging\GraphicalFunctions::getImageDimensions()
-     * @return bool TRUE if file is selectable.
-     */
-    protected function fileIsSelectableInFileList(FileInterface $file, array $imgInfo)
-    {
-        return true;
-    }
-
-    /**
-     * Render list of folders.
-     *
-     * @param Folder $baseFolder
-     * @return string HTML output
-     */
-    public function folderList(Folder $baseFolder)
-    {
-        $content = '';
-        $lang = $this->getLanguageService();
-        $folders = $baseFolder->getSubfolders();
-        $folderIdentifier = $baseFolder->getCombinedIdentifier();
-        // Create headline (showing number of folders):
-        $content .= $this->barheader(sprintf($lang->getLL('folders') . ' (%s):', count($folders)));
-        $titleLength = (int)$this->getBackendUser()->uc['titleLen'];
-        // Create the header of current folder:
-        $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($folderIdentifier)
-            . ', \'folder\', ' . GeneralUtility::quoteJSvalue($folderIdentifier) . ', ' . GeneralUtility::quoteJSvalue($folderIdentifier)
-            . ', \'\', \'\',\'\',1);">';
-        // Add the foder icon
-        $folderIcon = $aTag;
-        $folderIcon .= $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL)->render();
-        $folderIcon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs($baseFolder->getName(), $titleLength));
-        $folderIcon .= '</a>';
-        $content .= $folderIcon . '<br />';
-
-        $lines = array();
-        // Traverse the folder list:
-        foreach ($folders as $subFolder) {
-            $subFolderIdentifier = $subFolder->getCombinedIdentifier();
-            // Create folder icon:
-            $icon = '<span style="width: 16px; height: 16px; display: inline-block;"></span>';
-            $icon .= '<span title="' . htmlspecialchars($subFolder->getName()) . '">' . $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL)->render() . '</span>';
-            // Create links for adding the folder:
-            if ($this->P['itemName'] != '' && $this->P['formName'] != '') {
-                $aTag = '<a href="#" onclick="return set_folderpath(' . GeneralUtility::quoteJSvalue($subFolderIdentifier)
-                    . ');">';
-            } else {
-                $aTag = '<a href="#" onclick="return insertElement(\'\',' . GeneralUtility::quoteJSvalue($subFolderIdentifier)
-                    . ', \'folder\', ' . GeneralUtility::quoteJSvalue($subFolderIdentifier) . ', '
-                    . GeneralUtility::quoteJSvalue($subFolderIdentifier) . ', \'\', \'\');">';
-            }
-            if (strstr($subFolderIdentifier, ',') || strstr($subFolderIdentifier, '|')) {
-                // In case an invalid character is in the filepath, display error message:
-                $errorMessage = GeneralUtility::quoteJSvalue(sprintf($lang->getLL('invalidChar'), ', |'));
-                $aTag = ($aTag_alt = '<a href="#" onclick="alert(' . $errorMessage . ');return false;">');
-            } else {
-                // If foldername is OK, just add it:
-                $aTag_alt = substr($aTag, 0, -4) . ',\'\',1);">';
-            }
-            $aTag_e = '</a>';
-            // Combine icon and folderpath:
-            $foldernameAndIcon = $aTag_alt . $icon
-                . htmlspecialchars(GeneralUtility::fixed_lgd_cs($subFolder->getName(), $titleLength)) . $aTag_e;
-            if ($this->P['itemName'] != '') {
-                $lines[] = '
-                                       <tr class="bgColor4">
-                                               <td nowrap="nowrap">' . $foldernameAndIcon . '&nbsp;</td>
-                                               <td>&nbsp;</td>
-                                       </tr>';
-            } else {
-                $lines[] = '
-                                       <tr class="bgColor4">
-                                               <td nowrap="nowrap">' . $foldernameAndIcon . '&nbsp;</td>
-                                               <td>' . $aTag . '<span title="' . $lang->getLL('addToList', true) . '">' . $this->iconFactory->getIcon('actions-edit-add', Icon::SIZE_SMALL)->render() . '</span>' . $aTag_e . ' </td>
-                                               <td>&nbsp;</td>
-                                       </tr>';
-            }
-            $lines[] = '
-                                       <tr>
-                                               <td colspan="3"><span style="width: 1px; height: 3px; display: inline-block;"></span></td>
-                                       </tr>';
-        }
-        // Wrap all the rows in table tags:
-        $content .= '
-
-       <!--
-               Folder listing
-       -->
-                       <table border="0" cellpadding="0" cellspacing="1" id="typo3-folderList">
-                               ' . implode('', $lines) . '
-                       </table>';
-        // Return accumulated content for folderlisting:
-        return $content;
-    }
-
-    /**
-     * For RTE: This displays all IMAGES (gif,png,jpg) (from extensionList) from folder. Thumbnails are shown for images.
-     * This listing is of images located in the web-accessible paths ONLY - the listing is for drag-n-drop use in the RTE
-     *
-     * @param Folder $folder The folder path to expand
-     * @param string $extensionList List of file extensions to show
-     * @return string HTML output
-     */
-    public function TBE_dragNDrop(Folder $folder, $extensionList = '')
-    {
-        if (!$folder) {
-            return '';
-        }
-        $lang = $this->getLanguageService();
-        if (!$folder->getStorage()->isPublic()) {
-            // Print this warning if the folder is NOT a web folder
-            return GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('noWebFolder'), $lang->getLL('files'), FlashMessage::WARNING)
-                ->render();
-        }
-        $out = '';
-
-        // Read files from directory:
-        $extensionList = $extensionList == '*' ? '' : $extensionList;
-        $files = $this->getFilesInFolder($folder, $extensionList);
-
-        $out .= $this->barheader(sprintf($lang->getLL('files') . ' (%s):', count($files)));
-        $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
-        $picon = $this->iconFactory->getIcon('apps-filetree-folder-default', Icon::SIZE_SMALL)->render();
-        $picon .= htmlspecialchars(GeneralUtility::fixed_lgd_cs(basename($folder->getName()), $titleLen));
-        $out .= $picon . '<br />';
-        // Init row-array:
-        $lines = array();
-        // Add "drag-n-drop" message:
-        $infoText = GeneralUtility::makeInstance(FlashMessage::class, $lang->getLL('findDragDrop'), '', FlashMessage::INFO)
-            ->render();
-        $lines[] = '
-                       <tr>
-                               <td colspan="2">' . $infoText . '</td>
-                       </tr>';
-        // Traverse files:
-        foreach ($files as $fileObject) {
-            // URL of image:
-            $iUrl = GeneralUtility::rawurlencodeFP($fileObject->getPublicUrl(true));
-            // Show only web-images
-            $fileExtension = strtolower($fileObject->getExtension());
-            if (GeneralUtility::inList('gif,jpeg,jpg,png', $fileExtension)) {
-                $imgInfo = array(
-                    $fileObject->getProperty('width'),
-                    $fileObject->getProperty('height')
-                );
-                $pDim = $imgInfo[0] . 'x' . $imgInfo[1] . ' pixels';
-                $size = ' (' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes' . ($pDim ? ', ' . $pDim : '') . ')';
-                $filenameAndIcon = '<span title="' . htmlspecialchars($fileObject->getName() . $size) . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>';
-                if (GeneralUtility::_GP('noLimit')) {
-                    $maxW = 10000;
-                    $maxH = 10000;
-                } else {
-                    $maxW = 380;
-                    $maxH = 500;
-                }
-                $IW = $imgInfo[0];
-                $IH = $imgInfo[1];
-                if ($IW > $maxW) {
-                    $IH = ceil($IH / $IW * $maxW);
-                    $IW = $maxW;
-                }
-                if ($IH > $maxH) {
-                    $IW = ceil($IW / $IH * $maxH);
-                    $IH = $maxH;
-                }
-                // Make row:
-                $lines[] = '
-                                       <tr class="bgColor4">
-                                               <td nowrap="nowrap">' . $filenameAndIcon . '&nbsp;</td>
-                                               <td nowrap="nowrap">' . ($imgInfo[0] != $IW
-                        ? '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('noLimit' => '1')))
-                        . '" title="' . $lang->getLL('clickToRedrawFullSize', true) . '">' . $this->iconFactory->getIcon('status-dialog-warning', Icon::SIZE_SMALL)->render()
-                        . '</a>'
-                        : '')
-                    . $pDim . '&nbsp;</td>
-                                       </tr>';
-                $lines[] = '
-                                       <tr>
-                                               <td colspan="2"><img src="' . htmlspecialchars($iUrl) . '" data-htmlarea-file-uid="' . $fileObject->getUid()
-                    . '" width="' . htmlspecialchars($IW) . '" height="' . htmlspecialchars($IH) . '" border="1" alt="" /></td>
-                                       </tr>';
-                $lines[] = '
-                                       <tr>
-                                               <td colspan="2"><span style="width: 1px; height: 3px; display: inline-block;"></span></td>
-                                       </tr>';
-            }
-        }
-        // Finally, wrap all rows in a table tag:
-        $out .= '
-
-
-<!--
-       Filelisting / Drag-n-drop
--->
-                       <table border="0" cellpadding="0" cellspacing="1" id="typo3-dragBox">
-                               ' . implode('', $lines) . '
-                       </table>';
-
-        return $out;
-    }
-
-    /******************************************************************
-     *
-     * Miscellaneous functions
-     *
-     ******************************************************************/
-
-    /**
-     * Prints a 'header' where string is in a tablecell
-     *
-     * @param string $str The string to print in the header. The value is htmlspecialchars()'ed before output.
-     * @return string The header HTML (wrapped in a table)
-     */
-    public function barheader($str)
-    {
-        return '
-                       <!-- Bar header: -->
-                       <h3>' . htmlspecialchars($str) . '</h3>
-                       ';
-    }
-
-    /**
-     * For RTE/link: This prints the 'currentUrl'
-     *
-     * @param string $str URL value. The value is htmlspecialchars()'ed before output.
-     * @return string HTML content, wrapped in a table.
-     */
-    public function printCurrentUrl($str)
-    {
-        // Output the folder or file identifier, when working with files
-        if (isset($str) && MathUtility::canBeInterpretedAsInteger($str)) {
-            try {
-                $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($str);
-            } catch (Exception\FileDoesNotExistException $e) {
-                $fileObject = null;
-            }
-            $str = is_object($fileObject) ? $fileObject->getIdentifier() : '';
-        }
-        if ($str !== '') {
-            return '
-                               <!-- Print current URL -->
-                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
-                                       <tr>
-                                               <td>' . $this->getLanguageService()->getLL('currentLink', true) . ': '
-                            . htmlspecialchars(rawurldecode($str)) . '</td>
-                                       </tr>
-                               </table>';
-        } else {
-            return '';
-        }
-    }
-
-    /**
-     * For RTE/link: Parses the incoming URL and determines if it's a page, file, external or mail address.
-     *
-     * @param string $href HREF value tp analyse
-     * @param string $siteUrl The URL of the current website (frontend)
-     * @return array[] Array with URL information stored in assoc. keys: value, act (page, file, mail), pageid, cElement, info
-     */
-    public function parseCurUrl($href, $siteUrl)
-    {
-        $lang = $this->getLanguageService();
-        $href = trim($href);
-        if ($href) {
-            $info = array();
-            // Default is "url":
-            $info['value'] = $href;
-            $info['act'] = 'url';
-            if (!StringUtility::beginsWith($href, 'file://') && strpos($href, 'file:') !== false) {
-                $rel = substr($href, strpos($href, 'file:') + 5);
-                $rel = rawurldecode($rel);
-                try {
-                    // resolve FAL-api "file:UID-of-sys_file-record" and "file:combined-identifier"
-                    $fileOrFolderObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($rel);
-                    if ($fileOrFolderObject instanceof Folder) {
-                        $info['act'] = 'folder';
-                        $info['value'] = $fileOrFolderObject->getCombinedIdentifier();
-                    } elseif ($fileOrFolderObject instanceof File) {
-                        $info['act'] = 'file';
-                        $info['value'] = $fileOrFolderObject->getUid();
-                    } else {
-                        $info['value'] = $rel;
-                    }
-                } catch (Exception\FileDoesNotExistException $e) {
-                    // file was deleted or any other reason, don't select any item
-                    if (MathUtility::canBeInterpretedAsInteger($rel)) {
-                        $info['act'] = 'file';
-                    } else {
-                        $info['act'] = 'folder';
-                    }
-                    $info['value'] = '';
-                }
-            } elseif (StringUtility::beginsWith($href, $siteUrl)) {
-                // If URL is on the current frontend website:
-                // URL is a file, which exists:
-                if (file_exists(PATH_site . rawurldecode($href))) {
-                    $info['value'] = rawurldecode($href);
-                    if (@is_dir((PATH_site . $info['value']))) {
-                        $info['act'] = 'folder';
-                    } else {
-                        $info['act'] = 'file';
-                    }
-                } else {
-                    // URL is a page (id parameter)
-                    $uP = parse_url($href);
-
-                    $pp = preg_split('/^id=/', $uP['query']);
-                    $pp[1] = preg_replace('/&id=[^&]*/', '', $pp[1]);
-                    $parameters = explode('&', $pp[1]);
-                    $id = array_shift($parameters);
-                    if ($id) {
-                        // Checking if the id-parameter is an alias.
-                        if (!MathUtility::canBeInterpretedAsInteger($id)) {
-                            list($idPartR) = BackendUtility::getRecordsByField('pages', 'alias', $id);
-                            $id = (int)$idPartR['uid'];
-                        }
-                        $pageRow = BackendUtility::getRecordWSOL('pages', $id);
-                        $titleLen = (int)$this->getBackendUser()->uc['titleLen'];
-                        $info['value'] = ((((($lang->getLL('page', true) . ' \'')
-                                        . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageRow['title'], $titleLen)))
-                                        . '\' (ID:') . $id) . ($uP['fragment'] ? ', #' . $uP['fragment'] : '')) . ')';
-                        $info['pageid'] = $id;
-                        $info['cElement'] = $uP['fragment'];
-                        $info['act'] = 'page';
-                        $info['query'] = $parameters[0] ? '&' . implode('&', $parameters) : '';
-                    }
-                }
-            } else {
-                // Email link:
-                if (strtolower(substr($href, 0, 7)) === 'mailto:') {
-                    $info['value'] = trim(substr($href, 7));
-                    $info['act'] = 'mail';
-                }
-            }
-            $info['info'] = $info['value'];
-        } else {
-            // NO value input:
-            $info = array();
-            $info['info'] = $lang->getLL('none');
-            $info['value'] = '';
-            $info['act'] = 'page';
-        }
-        // let the hook have a look
-        foreach ($this->hookObjects as $hookObject) {
-            $info = $hookObject->parseCurrentUrl($href, $siteUrl, $info);
-        }
-        return $info;
-    }
-
-    /**
-     * Setter for the class that should be used by TBE_expandPage() to generate the record list.
-     * This method is intended to be used by Extensions that implement their own browsing functionality.
-     *
-     * @param ElementBrowserRecordList $recordList
-     * @return void
-     * @api
-     */
-    public function setRecordList(ElementBrowserRecordList $recordList)
-    {
-        $this->recordList = $recordList;
-    }
-
-    /**
-     * Makes an upload form for uploading files to the filemount the user is browsing.
-     * The files are uploaded to the tce_file.php script in the core which will handle the upload.
-     *
-     * @param Folder $folderObject
-     * @return string HTML for an upload form.
-     */
-    public function uploadForm(Folder $folderObject)
-    {
-        if (!$folderObject->checkActionPermission('write')) {
-            return '';
-        }
-        // Read configuration of upload field count
-        $userSetting = $this->getBackendUser()->getTSConfigVal('options.folderTree.uploadFieldsInLinkBrowser');
-        $count = isset($userSetting) ? (int)$userSetting : 1;
-        if ($count === 0) {
-            return '';
-        }
-        $pArr = explode('|', $this->bparams);
-        $allowedExtensions = isset($pArr[3]) ? GeneralUtility::trimExplode(',', $pArr[3], true) : [];
-
-        $count = (int)$count === 0 ? 1 : (int)$count;
-        // Create header, showing upload path:
-        $header = $folderObject->getIdentifier();
-        $lang = $this->getLanguageService();
-        // Create a list of allowed file extensions with the readable format "youtube, vimeo" etc.
-        $fileExtList = array();
-        foreach ($allowedExtensions as $fileExt) {
-            if (GeneralUtility::verifyFilenameAgainstDenyPattern($fileExt)) {
-                $fileExtList[] = '<span class="label label-success">' . strtoupper(htmlspecialchars($fileExt)) . '</span>';
-            }
-        }
-        $code = '
-                       <br />
-                       <!--
-                               Form, for uploading files:
-                       -->
-                       <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" method="post" name="editform"'
-            . ' id="typo3-uplFilesForm" enctype="multipart/form-data">
-                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-uplFiles">
-                                       <tr>
-                                               <td>' . $this->barheader($lang->sL(
-                                'LLL:EXT:lang/locallang_core.xlf:file_upload.php.pagetitle', true) . ':') . '</td>
-                                       </tr>
-                                       <tr>
-                                               <td class="c-wCell c-hCell"><strong>' . $lang->getLL('path', true) . ':</strong> '
-                            . htmlspecialchars($header) . '</td>
-                                       </tr>
-                                       <tr>
-                                               <td class="c-wCell c-hCell">';
-        // Traverse the number of upload fields:
-        $combinedIdentifier = $folderObject->getCombinedIdentifier();
-        for ($a = 1; $a <= $count; $a++) {
-            $code .= '<input type="file" multiple="multiple" name="upload_' . $a . '[]"' . $this->doc->formWidth(35)
-                    . ' size="50" />
-                               <input type="hidden" name="file[upload][' . $a . '][target]" value="'
-                    . htmlspecialchars($combinedIdentifier) . '" />
-                               <input type="hidden" name="file[upload][' . $a . '][data]" value="' . $a . '" /><br />';
-        }
-        // Make footer of upload form, including the submit button:
-        $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode
-            . '&expandFolder=' . rawurlencode($combinedIdentifier)
-            . '&bparams=' . rawurlencode($this->bparams)
-            . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : '');
-        $code .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($redirectValue) . '" />';
-
-        if (!empty($fileExtList)) {
-            $code .= '
-                               <div class="help-block">
-                                       ' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:cm.allowedFileExtensions', true) . '<br>
-                                       ' . implode(' ', $fileExtList) . '
-                               </div>
-                       ';
-        }
-
-        $code .= '
-                       <div id="c-override">
-                               <label>
-                                       <input type="checkbox" name="overwriteExistingFiles" id="overwriteExistingFiles" value="1" /> '
-                    . $lang->sL('LLL:EXT:lang/locallang_misc.xlf:overwriteExistingFiles', true) . '
-                               </label>
-                       </div>
-                       <input class="btn btn-default" type="submit" name="submit" value="'
-                . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_upload.php.submit', true) . '" />
-               ';
-        $code .= '</td>
-                                       </tr>
-                               </table>
-                       </form>';
-
-        // Add online media
-        // Create a list of allowed file extensions in a readable format "youtube, vimeo" etc.
-        $fileExtList = array();
-        $onlineMediaFileExt = OnlineMediaHelperRegistry::getInstance()->getSupportedFileExtensions();
-        foreach ($onlineMediaFileExt as $fileExt) {
-            if (
-                GeneralUtility::verifyFilenameAgainstDenyPattern($fileExt)
-                && (empty($allowedExtensions) || in_array($fileExt, $allowedExtensions, true))
-            ) {
-                $fileExtList[] = '<span class="label label-success">' . strtoupper(htmlspecialchars($fileExt)) . '</span>';
-            }
-        }
-        if (!empty($fileExtList)) {
-            $code .= '
-                               <!--
-                       Form, adding online media urls:
-                               -->
-                               <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('online_media')) . '" method="post" name="editform1"'
-                . ' id="typo3-addMediaForm">
-                                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-uplFiles">
-                                               <tr>
-                                                       <td>' . $this->barheader($lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media', true) . ':') . '</td>
-                                               </tr>
-                                               <tr>
-                                                       <td class="c-wCell c-hCell"><strong>' . $lang->getLL('path', true) . ':</strong> '
-                . htmlspecialchars($header) . '</td>
-                                               </tr>
-                                               <tr>
-                                                       <td class="c-wCell c-hCell">
-                                                               <input type="text" name="file[newMedia][0][url]"' . $this->doc->formWidth(35)
-                . ' size="50" placeholder="' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.placeholder', true) . '" />
-                                       <input type="hidden" name="file[newMedia][0][target]" value="'
-                . htmlspecialchars($folderObject->getCombinedIdentifier()) . '" />
-                                       <input type="hidden" name="file[newMedia][0][allowed]" value="'
-                . htmlspecialchars(implode(',', $allowedExtensions)) . '" />
-                                       <button>' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.submit', true) . '</button>
-                                       <div class="help-block">
-                                               ' . $lang->sL('LLL:EXT:lang/locallang_core.xlf:online_media.new_media.allowedProviders') . '<br>
-                                               ' . implode(' ', $fileExtList) . '
-                                       </div>
-                                               ';
-        }
-
-        // Make footer of upload form, including the submit button:
-        $redirectValue = $this->getThisScript()
-            . 'act=' . $this->act
-            . '&mode=' . $this->mode
-            . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier())
-            . '&bparams=' . rawurlencode($this->bparams)
-            . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : '');
-        $code .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($redirectValue) . '" />';
-
-        $code .= '</td>
-                                       </tr>
-                               </table>
-                       </form><br />';
-
-
-        return $code;
-    }
-
-    /**
-     * For TBE: Makes a form for creating new folders in the filemount the user is browsing.
-     * The folder creation request is sent to the tce_file.php script in the core which will handle the creation.
-     *
-     * @param Folder $folderObject Absolute filepath on server in which to create the new folder.
-     * @return string HTML for the create folder form.
-     */
-    public function createFolder(Folder $folderObject)
-    {
-        if (!$folderObject->checkActionPermission('write')) {
-            return '';
-        }
-        $backendUser = $this->getBackendUser();
-        if (!($backendUser->isAdmin() || $backendUser->getTSConfigVal('options.createFoldersInEB'))) {
-            return '';
-        }
-        // Don't show Folder-create form if it's denied
-        if ($backendUser->getTSConfigVal('options.folderTree.hideCreateFolder')) {
-            return '';
-        }
-        $lang = $this->getLanguageService();
-        // Create header, showing upload path:
-        $header = $folderObject->getIdentifier();
-        $code = '
-
-                       <!--
-                               Form, for creating new folders:
-                       -->
-                       <form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_file')) . '" method="post" name="editform2" id="typo3-crFolderForm">
-                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-crFolder">
-                                       <tr>
-                                               <td>' . $this->barheader($lang->sL(
-                                'LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.pagetitle') . ':') . '</td>
-                                       </tr>
-                                       <tr>
-                                               <td class="c-wCell c-hCell"><strong>'
-                            . $lang->getLL('path', true) . ':</strong> ' . htmlspecialchars($header) . '</td>
-                                       </tr>
-                                       <tr>
-                                               <td class="c-wCell c-hCell">';
-        // Create the new-folder name field:
-        $a = 1;
-        $code .= '<input' . $this->doc->formWidth(20) . ' type="text" name="file[newfolder][' . $a . '][data]" />'
-                . '<input type="hidden" name="file[newfolder][' . $a . '][target]" value="'
-                . htmlspecialchars($folderObject->getCombinedIdentifier()) . '" />';
-        // Make footer of upload form, including the submit button:
-        $redirectValue = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode
-            . '&expandFolder=' . rawurlencode($folderObject->getCombinedIdentifier())
-            . '&bparams=' . rawurlencode($this->bparams)
-            . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : '');
-        $code .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($redirectValue) . '" />'
-            . '<input class="btn btn-default" type="submit" name="submit" value="'
-            . $lang->sL('LLL:EXT:lang/locallang_core.xlf:file_newfolder.php.submit', true) . '" />';
-        $code .= '</td>
-                                       </tr>
-                               </table>
-                       </form>';
-        return $code;
-    }
-
-    /**
-     * Get the HTML data required for a bulk selection of files of the TYPO3 Element Browser.
-     *
-     * @param int $filesCount Number of files currently displayed
-     * @return string HTML data required for a bulk selection of files - if $filesCount is 0, nothing is returned
-     */
-    public function getBulkSelector($filesCount)
-    {
-        if (!$filesCount) {
-            return '';
-        }
-
-        $lang = $this->getLanguageService();
-        $labelToggleSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:toggleSelection', true);
-        $labelImportSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:importSelection', true);
-        // Getting flag for showing/not showing thumbnails:
-        $noThumbsInEB = $this->getBackendUser()->getTSConfigVal('options.noThumbsInEB');
-        $out = '<div style="padding-top:10px;">' . '<a href="#" onclick="BrowseLinks.Selector.handle()"'
-            . 'title="' . $labelImportSelection . '">'
-            . $this->iconFactory->getIcon('actions-document-import-t3d', Icon::SIZE_SMALL)->render()
-            . $labelImportSelection . '</a>&nbsp;&nbsp;&nbsp;'
-            . '<a href="#" onclick="BrowseLinks.Selector.toggle()" title="' . $labelToggleSelection . '">'
-            . $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL)->render()
-            . $labelToggleSelection . '</a>' . '</div>';
-        if (!$noThumbsInEB && $this->selectedFolder) {
-            // MENU-ITEMS, fetching the setting for thumbnails from File>List module:
-            $_MOD_MENU = array('displayThumbs' => '');
-            $_MCONF['name'] = 'file_list';
-            $_MOD_SETTINGS = BackendUtility::getModuleData($_MOD_MENU, GeneralUtility::_GP('SET'), $_MCONF['name']);
-            $addParams = '&act=' . $this->act . '&mode=' . $this->mode
-                . '&expandFolder=' . rawurlencode($this->selectedFolder->getCombinedIdentifier())
-                . '&bparams=' . rawurlencode($this->bparams);
-            $thumbNailCheck = '<div class="checkbox" style="padding:5px 0 15px 0"><label for="checkDisplayThumbs">' . BackendUtility::getFuncCheck('', 'SET[displayThumbs]', $_MOD_SETTINGS['displayThumbs'],
-                    GeneralUtility::_GP('M') ? '' : $this->thisScript, $addParams, 'id="checkDisplayThumbs"')
-                . $lang->sL('LLL:EXT:lang/locallang_mod_file_list.xlf:displayThumbs', true) . '</label></div>';
-            $out .= $thumbNailCheck;
-        } else {
-            $out .= '<div style="padding-top: 15px;"></div>';
-        }
-        return $out;
-    }
-
-    /**
-     * Get the HTML data required for the file search field of the TYPO3 Element Browser.
-     *
-     * @return string HTML data required for the search field in the file list of the Element Browser
-     */
-    protected function getFileSearchField()
-    {
-        $action = $this->getThisScript() . 'act=' . $this->act . '&mode=' . $this->mode
-            . '&bparams=' . rawurlencode($this->bparams)
-            . (is_array($this->P) ? GeneralUtility::implodeArrayForUrl('P', $this->P) : '');
-        $out = '
-                       <form method="post" action="' . htmlspecialchars($action) . '" style="padding-bottom: 15px;">
-                               <div class="input-group">
-                                       <input class="form-control" type="text" name="searchWord" value="' . htmlspecialchars($this->searchWord) . '">
-                                       <span class="input-group-btn">
-                                               <button class="btn btn-default" type="submit">' . $this->getLanguageService()->sL('LLL:EXT:filelist/Resources/Private/Language/locallang.xlf:search', true) . '</button>
-                                       </span>
-                               </div>
-                       </form>';
-        return $out;
-    }
-
-    /**
-     * Determines whether submitted field change functions are valid
-     * and are coming from the system and not from an external abuse.
-     *
-     * @param bool $handleFlexformSections Whether to handle flexform sections differently
-     * @return bool Whether the submitted field change functions are valid
-     */
-    protected function areFieldChangeFunctionsValid($handleFlexformSections = false)
-    {
-        $result = false;
-        if (isset($this->P['fieldChangeFunc']) && is_array($this->P['fieldChangeFunc']) && isset($this->P['fieldChangeFuncHash'])) {
-            $matches = array();
-            $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i';
-            $fieldChangeFunctions = $this->P['fieldChangeFunc'];
-            // Special handling of flexform sections:
-            // Field change functions are modified in JavaScript, thus the hash is always invalid
-            if ($handleFlexformSections && preg_match($pattern, $this->P['itemName'], $matches)) {
-                $originalName = $matches[1];
-                $cleanedName = $matches[2] . $matches[4];
-                foreach ($fieldChangeFunctions as &$value) {
-                    $value = str_replace($originalName, $cleanedName, $value);
-                }
-                unset($value);
-            }
-            $result = $this->P['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions));
-        }
-        return $result;
-    }
-
-    /**
-     * Check if a temporary tree mount is set and return a cancel button
-     *
-     * @return string
-     */
-    protected function getTemporaryTreeMountCancelNotice()
-    {
-        if ((int)$this->getBackendUser()->getSessionData('pageTree_temporaryMountPoint') === 0) {
-            return '';
-        }
-        $link = '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('setTempDBmount' => 0))) . '">'
-            . $this->getLanguageService()->sl('LLL:EXT:lang/locallang_core.xlf:labels.temporaryDBmount', true) . '</a>';
-        /** @var FlashMessage $flashMessage */
-        $flashMessage = GeneralUtility::makeInstance(
-            FlashMessage::class,
-            $link,
-            '',
-            FlashMessage::INFO
-        );
-        return $flashMessage->render();
-    }
-
-    /**
-     * Get a list of Files in a folder filtered by extension
-     *
-     * @param Folder $folder
-     * @param string $extensionList
-     * @return File[]
-     */
-    protected function getFilesInFolder(Folder $folder, $extensionList)
-    {
-        if ($extensionList !== '') {
-            /** @var FileExtensionFilter $filter */
-            $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
-            $filter->setAllowedFileExtensions($extensionList);
-            $folder->setFileAndFolderNameFilters(array(array($filter, 'filterFileList')));
-        }
-        return $folder->getFiles();
-    }
-
-    /**
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-
-    /**
-     * @return DatabaseConnection
-     */
-    protected function getDatabaseConnection()
-    {
-        return $GLOBALS['TYPO3_DB'];
-    }
-
-    /**
-     * @return PageRenderer
-     */
-    protected function getPageRenderer()
-    {
-        if ($this->pageRenderer === null) {
-            $this->pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-        }
-        return $this->pageRenderer;
-    }
-}
index d8c98d6..5f2441a 100644 (file)
@@ -385,10 +385,10 @@ class FileBrowser extends AbstractElementBrowser implements ElementBrowserInterf
         $labelToggleSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:toggleSelection', true);
         $labelImportSelection = $lang->sL('LLL:EXT:lang/locallang_browse_links.xlf:importSelection', true);
 
-        $out = '<div style="padding-top:10px;">' . '<a href="#" id="t3-js-importSelection" title="' . $labelImportSelection . '">'
+        $out = '<div style="padding-top:10px;">' . '<a href="#" id="t3js-importSelection" title="' . $labelImportSelection . '">'
             . $this->iconFactory->getIcon('actions-document-import-t3d', Icon::SIZE_SMALL)
             . $labelImportSelection . '</a>&nbsp;&nbsp;&nbsp;'
-            . '<a href="#" id="t3-js-toggleSelection" title="' . $labelToggleSelection . '">'
+            . '<a href="#" id="t3js-toggleSelection" title="' . $labelToggleSelection . '">'
             . $this->iconFactory->getIcon('actions-document-select', Icon::SIZE_SMALL)
             . $labelToggleSelection . '</a>' . '</div>';
 
index 7cb8a4f..5308a81 100644 (file)
@@ -163,7 +163,7 @@ class FolderBrowser extends AbstractElementBrowser implements ElementBrowserInte
             if (strstr($subFolderIdentifier, ',') || strstr($subFolderIdentifier, '|')) {
                 // In case an invalid character is in the filepath, display error message:
                 $errorMessage = sprintf($lang->getLL('invalidChar', true), ', |');
-                $aTag = '<a href="#" class="t3-js-folderIdError" data-message="' . $errorMessage . '">';
+                $aTag = '<a href="#" class="t3js-folderIdError" data-message="' . $errorMessage . '">';
             }
             $aTag_e = '</a>';
             // Combine icon and folderpath:
diff --git a/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php b/typo3/sysext/recordlist/Classes/Controller/AbstractLinkBrowserController.php
new file mode 100644 (file)
index 0000000..b7b6c0b
--- /dev/null
@@ -0,0 +1,663 @@
+<?php
+namespace TYPO3\CMS\Recordlist\Controller;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use TYPO3\CMS\Backend\Routing\Router;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
+use TYPO3\CMS\Backend\Template\DocumentTemplate;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Service\DependencyOrderingService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface;
+
+/**
+ * Script class for the Link Browser window.
+ */
+abstract class AbstractLinkBrowserController
+{
+    /**
+     * @var DocumentTemplate
+     */
+    protected $doc;
+
+    /**
+     * @var array
+     */
+    protected $parameters;
+
+    /**
+     * URL of current request
+     *
+     * @var string
+     */
+    protected $thisScript = '';
+
+    /**
+     * @var LinkHandlerInterface[]
+     */
+    protected $linkHandlers = [];
+
+    /**
+     * All parts of the current link
+     *
+     * Comprised of url information and additional link parameters.
+     *
+     * @var string[]
+     */
+    protected $currentLinkParts = [];
+
+    /**
+     * Link handler responsible for the current active link
+     *
+     * @var LinkHandlerInterface $currentLinkHandler
+     */
+    protected $currentLinkHandler;
+
+    /**
+     * The ID of the currently active link handler
+     *
+     * @var string
+     */
+    protected $currentLinkHandlerId;
+
+    /**
+     * Link handler to be displayed
+     *
+     * @var LinkHandlerInterface $displayedLinkHandler
+     */
+    protected $displayedLinkHandler;
+
+    /**
+     * The ID of the displayed link handler
+     *
+     * This is read from the 'act' GET parameter
+     *
+     * @var string
+     */
+    protected $displayedLinkHandlerId = '';
+
+    /**
+     * List of available link attribute fields
+     *
+     * @var string[]
+     */
+    protected $linkAttributeFields = [];
+
+    /**
+     * Values of the link attributes
+     *
+     * @var string[]
+     */
+    protected $linkAttributeValues = [];
+
+    /**
+     * @var array
+     */
+    protected $hookObjects = [];
+
+    /**
+     * Constructor
+     */
+    public function __construct()
+    {
+        $this->initHookObjects();
+        $this->init();
+    }
+
+    /**
+     * Initialize the controller
+     *
+     * @return void
+     */
+    protected function init()
+    {
+        $this->getLanguageService()->includeLLFile('EXT:lang/locallang_browse_links.xlf');
+    }
+
+    /**
+     * Initialize hook objects implementing the interface
+     *
+     * @throws \UnexpectedValueException
+     * @return void
+     */
+    protected function initHookObjects()
+    {
+        if (
+            isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks'])
+            && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks'])
+        ) {
+            $hooks = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies(
+                $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks']
+            );
+            foreach ($hooks as $key => $hook) {
+                $this->hookObjects[] = GeneralUtility::makeInstance($hook['handler']);
+            }
+        }
+    }
+
+    /**
+     * Injects the request object for the current request or subrequest
+     * As this controller goes only through the main() method, it is rather simple for now
+     *
+     * @param ServerRequestInterface $request the current request
+     * @param ResponseInterface $response the prepared response object
+     * @return ResponseInterface the response with the content
+     */
+    public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
+    {
+        $this->determineScriptUrl($request);
+        $this->initVariables($request);
+        $this->loadLinkHandlers();
+        $this->initCurrentUrl();
+
+        $menuData = $this->buildMenuArray();
+        $renderLinkAttributeFields = $this->renderLinkAttributeFields();
+        $browserContent = $this->displayedLinkHandler->render($request);
+
+        $this->initDocumentTemplate();
+        $content = $this->doc->startPage('Link Browser');
+        $content .= $this->doc->getFlashMessages();
+
+        if (!empty($this->currentLinkParts)) {
+            $content .= $this->renderCurrentUrl();
+        }
+        $content .= $this->doc->getTabMenuRaw($menuData);
+        $content .= $renderLinkAttributeFields;
+
+        $content .= '<div class="linkBrowser-tabContent">' . $browserContent . '</div>';
+        $content .= $this->doc->endPage();
+
+        $response->getBody()->write($this->doc->insertStylesAndJS($content));
+        return $response;
+    }
+
+    /**
+     * Sets the script url depending on being a module or script request
+     *
+     * @param ServerRequestInterface $request
+     *
+     * @throws \TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException
+     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
+     */
+    protected function determineScriptUrl(ServerRequestInterface $request)
+    {
+        if ($routePath = $request->getQueryParams()['route']) {
+            $router = GeneralUtility::makeInstance(Router::class);
+            $route = $router->match($routePath);
+            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+            $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'));
+        } elseif ($moduleName = $request->getQueryParams()['M']) {
+            $this->thisScript = BackendUtility::getModuleUrl($moduleName);
+        } else {
+            $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
+        }
+    }
+
+    /**
+     * @param ServerRequestInterface $request
+     */
+    protected function initVariables(ServerRequestInterface $request)
+    {
+        $queryParams = $request->getQueryParams();
+        $act = isset($queryParams['act']) ? $queryParams['act'] : '';
+        // @deprecated since CMS 7, remove with CMS 8
+        if (strpos($act, '|')) {
+            GeneralUtility::deprecationLog('Using multiple values for the "act" parameter in the link wizard is deprecated. Only a single value is allowed. Values were: ' . $act);
+            $act = array_shift(explode('|', $act));
+        }
+        $this->displayedLinkHandlerId = $act;
+        $this->parameters = isset($queryParams['P']) ? $queryParams['P'] : [];
+        $this->linkAttributeValues = isset($queryParams['linkAttributes']) ? $queryParams['linkAttributes'] : [];
+    }
+
+    /**
+     * @return void
+     * @throws \UnexpectedValueException
+     */
+    protected function loadLinkHandlers()
+    {
+        $linkHandlers = $this->getLinkHandlers();
+        if (empty($linkHandlers)) {
+            throw new \UnexpectedValueException('No link handlers are configured. Check page TSconfig TCEMAIN.linkHandlers.', 1442787911);
+        }
+
+        $lang = $this->getLanguageService();
+        foreach ($linkHandlers as $identifier => $configuration) {
+            $identifier = rtrim($identifier, '.');
+            /** @var LinkHandlerInterface $handler */
+            $handler = GeneralUtility::makeInstance($configuration['handler']);
+            $handler->initialize(
+                $this,
+                $identifier,
+                isset($configuration['configuration.']) ? $configuration['configuration.'] : []
+            );
+
+            $this->linkHandlers[$identifier] = [
+                'handlerInstance' => $handler,
+                'label' => $lang->sL($configuration['label'], true),
+                'displayBefore' => isset($configuration['displayBefore']) ? GeneralUtility::trimExplode(',', $configuration['displayBefore']) : [],
+                'displayAfter' => isset($configuration['displayAfter']) ? GeneralUtility::trimExplode(',', $configuration['displayAfter']) : [],
+                'scanBefore' => isset($configuration['scanBefore']) ? GeneralUtility::trimExplode(',', $configuration['scanBefore']) : [],
+                'scanAfter' => isset($configuration['scanAfter']) ? GeneralUtility::trimExplode(',', $configuration['scanAfter']) : [],
+                'addParams' => isset($configuration['addParams']) ? $configuration['addParams'] : '',
+            ];
+        }
+    }
+
+    /**
+     * Reads the configured link handlers from page TSconfig
+     *
+     * @return array
+     */
+    protected function getLinkHandlers()
+    {
+        $pageTSconfig = BackendUtility::getPagesTSconfig($this->getCurrentPageId());
+        $pageTSconfig = $this->getBackendUser()->getTSConfig('TCEMAIN.linkHandler.', $pageTSconfig);
+        $linkHandlers = (array)$pageTSconfig['properties'];
+
+        foreach ($this->hookObjects as $hookObject) {
+            if (method_exists($hookObject, 'modifyLinkHandlers')) {
+                $linkHandlers = $hookObject->modifyLinkHandlers($linkHandlers, $this->currentLinkParts);
+            }
+        }
+
+        return $linkHandlers;
+    }
+
+    /**
+     * Initialize $this->currentLinkParts and $this->currentLinkHandler
+     *
+     * @return void
+     */
+    protected function initCurrentUrl()
+    {
+        if (empty($this->currentLinkParts)) {
+            return;
+        }
+
+        $orderedHandlers = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($this->linkHandlers, 'scanBefore', 'scanAfter');
+
+        // find responsible handler for current link
+        foreach ($orderedHandlers as $key => $configuration) {
+            /** @var LinkHandlerInterface $handler */
+            $handler = $configuration['handlerInstance'];
+            if ($handler->canHandleLink($this->currentLinkParts)) {
+                $this->currentLinkHandler = $handler;
+                $this->currentLinkHandlerId = $key;
+                break;
+            }
+        }
+        // reset the link if we have no handler for it
+        if (!$this->currentLinkHandler) {
+            $this->currentLinkParts = [];
+        }
+
+        // overwrite any preexisting
+        foreach ($this->currentLinkParts as $key => $part) {
+            if ($key !== 'url') {
+                $this->linkAttributeValues[$key] = $part;
+            }
+        }
+    }
+
+    /**
+     * Initialize document template object
+     *
+     *  @return void
+     */
+    protected function initDocumentTemplate()
+    {
+        $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
+        $this->doc->bodyTagId = 'typo3-browse-links-php';
+
+        foreach ($this->getBodyTagAttributes() as $attributeName => $value) {
+            $this->doc->bodyTagAdditions .= ' ' . $attributeName . '="' . htmlspecialchars($value) . '"';
+        }
+
+        // Finally, add the accumulated JavaScript to the template object:
+        // also unset the default jumpToUrl() function before
+        unset($this->doc->JScodeArray['jumpToUrl']);
+    }
+
+    /**
+     * Render the currently set URL
+     *
+     * @return string
+     */
+    protected function renderCurrentUrl()
+    {
+        return '<!-- Print current URL -->
+                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
+                                       <tr>
+                                               <td>' . $this->getLanguageService()->getLL('currentLink', true) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . '</td>
+                                       </tr>
+                               </table>';
+    }
+
+    /**
+     * Returns an array definition of the top menu
+     *
+     * @return mixed[][]
+     */
+    protected function buildMenuArray()
+    {
+        $allowedItems = $this->getAllowedItems();
+        if ($this->displayedLinkHandlerId && !in_array($this->displayedLinkHandlerId, $allowedItems, true)) {
+            $this->displayedLinkHandlerId = '';
+        }
+
+        $allowedHandlers = array_flip($allowedItems);
+        $menuDef = array();
+        foreach ($this->linkHandlers as $identifier => $configuration) {
+            if (!isset($allowedHandlers[$identifier])) {
+                continue;
+            }
+
+            /** @var LinkHandlerInterface $handlerInstance */
+            $handlerInstance = $configuration['handlerInstance'];
+            $isActive = $this->displayedLinkHandlerId === $identifier || !$this->displayedLinkHandlerId && $handlerInstance === $this->currentLinkHandler;
+            if ($isActive) {
+                $this->displayedLinkHandler = $handlerInstance;
+                if (!$this->displayedLinkHandlerId) {
+                    $this->displayedLinkHandlerId = $this->currentLinkHandlerId;
+                }
+            }
+
+            if ($configuration['addParams']) {
+                $addParams = $configuration['addParams'];
+            } else {
+                $parameters = GeneralUtility::implodeArrayForUrl('', $this->getUrlParameters(['act' => $identifier]));
+                $addParams = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?' . ltrim($parameters, '&')) . ');return false;"';
+            }
+            $menuDef[$identifier] = [
+                'isActive' => $isActive,
+                'label' => $configuration['label'],
+                'url' => '#',
+                'addParams' => $addParams,
+                'before' => $configuration['displayBefore'],
+                'after' => $configuration['displayAfter']
+            ];
+        }
+
+        $menuDef = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($menuDef);
+
+        // if there is no active tab
+        if (!$this->displayedLinkHandler) {
+            // empty the current link
+            $this->currentLinkParts = [];
+            $this->currentLinkHandler = null;
+            $this->currentLinkHandler = '';
+            // select first tab
+            reset($menuDef);
+            $this->displayedLinkHandlerId = key($menuDef);
+            $this->displayedLinkHandler = $this->linkHandlers[$this->displayedLinkHandlerId]['handlerInstance'];
+            $menuDef[$this->displayedLinkHandlerId]['isActive'] = true;
+        }
+
+        return $menuDef;
+    }
+
+    /**
+     * Get the allowed items or tabs
+     *
+     * @return string[]
+     */
+    protected function getAllowedItems()
+    {
+        $allowedItems = array_keys($this->linkHandlers);
+
+        foreach ($this->hookObjects as $hookObject) {
+            if (method_exists($hookObject, 'modifyAllowedItems')) {
+                $allowedItems = $hookObject->modifyAllowedItems($allowedItems, $this->currentLinkParts);
+            }
+        }
+
+        // Initializing the action value, possibly removing blinded values etc:
+        $blindLinkOptions = isset($this->parameters['params']['blindLinkOptions'])
+            ? GeneralUtility::trimExplode(',', $this->parameters['params']['blindLinkOptions'])
+            : [];
+        $allowedItems = array_diff($allowedItems, $blindLinkOptions);
+
+        return $allowedItems;
+    }
+
+    /**
+     * Get the allowed link attributes
+     *
+     * @return string[]
+     */
+    protected function getAllowedLinkAttributes()
+    {
+        $allowedLinkAttributes = $this->displayedLinkHandler->getLinkAttributes();
+
+        // Removing link fields if configured
+        $blindLinkFields = isset($this->parameters['params']['blindLinkFields'])
+            ? GeneralUtility::trimExplode(',', $this->parameters['params']['blindLinkFields'], true)
+            : [];
+        $allowedLinkAttributes = array_diff($allowedLinkAttributes, $blindLinkFields);
+
+        return $allowedLinkAttributes;
+    }
+
+    /**
+     * Renders the link attributes for the selected link handler
+     *
+     * @return string
+     */
+    public function renderLinkAttributeFields()
+    {
+        $fieldRenderingDefinitions = $this->getLinkAttributeFieldDefinitions();
+
+        $fieldRenderingDefinitions = $this->displayedLinkHandler->modifyLinkAttributes($fieldRenderingDefinitions);
+
+        $this->linkAttributeFields = $this->getAllowedLinkAttributes();
+
+        $content = '';
+        foreach ($this->linkAttributeFields as $attribute) {
+            $content .= $fieldRenderingDefinitions[$attribute];
+        }
+
+        // add update button if appropriate
+        if (!empty($this->currentLinkParts) && $this->displayedLinkHandler === $this->currentLinkHandler && $this->currentLinkHandler->isUpdateSupported()) {
+            $content .= '
+                               <form action="" name="lparamsform" id="lparamsform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
+                                       <tr><td>
+                                               <input class="btn btn-default t3js-linkCurrent" type="submit" value="' . $this->getLanguageService()->getLL('update', true) . '" />
+                                       </td></tr>
+                                       </table>
+                               </form><br /><br />';
+        }
+
+        return $content;
+    }
+
+    /**
+     * Create an array of link attribute field rendering definitions
+     *
+     * @return string[]
+     */
+    protected function getLinkAttributeFieldDefinitions()
+    {
+        $lang = $this->getLanguageService();
+
+        $fieldRenderingDefinitions = [];
+        $fieldRenderingDefinitions['target'] = '
+                       <!--
+                               Selecting target for link:
+                       -->
+                               <form action="" name="ltargetform" id="ltargetform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
+                                               <tr>
+                                                       <td style="width: 96px;">' . $lang->getLL('target', true) . ':</td>
+                                                       <td>
+                                                               <input type="text" name="ltarget" class="t3js-linkTarget" value="' . htmlspecialchars($this->linkAttributeValues['target']) . '" />
+                                                               <select name="ltarget_type" class="t3js-targetPreselect">
+                                                                       <option value=""></option>
+                                                                       <option value="_top">' . $lang->getLL('top', true) . '</option>
+                                                                       <option value="_blank">' . $lang->getLL('newWindow', true) . '</option>
+                                                               </select>
+                                                       </td>
+                                               </tr>
+                                       </table>
+                               </form>';
+
+        $fieldRenderingDefinitions['title'] = '
+                               <!--
+                                       Selecting title for link:
+                               -->
+                               <form action="" name="ltitleform" id="ltitleform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
+                                               <tr>
+                                                       <td style="width: 96px;">' . $lang->getLL('title', true) . '</td>
+                                                       <td><input type="text" name="ltitle" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['title']) . '" /></td>
+                                               </tr>
+                                       </table>
+                               </form>
+                       ';
+
+        $fieldRenderingDefinitions['class'] = '
+                               <!--
+                                       Selecting class for link:
+                               -->
+                               <form action="" name="lclassform" id="lclassform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
+                                               <tr>
+                                                       <td style="width: 96px;">' . $lang->getLL('class', true) . '</td>
+                                                       <td><input type="text" name="lclass" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['class']) . '" /></td>
+                                               </tr>
+                                       </table>
+                               </form>
+                       ';
+
+        $fieldRenderingDefinitions['params'] = '
+                               <!--
+                                       Selecting params for link:
+                               -->
+                               <form action="" name="lparamsform" id="lparamsform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
+                                               <tr>
+                                                       <td style="width: 96px;">' . $lang->getLL('params', true) . '</td>
+                                                       <td><input type="text" name="lparams" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['params']) . '" /></td>
+                                               </tr>
+                                       </table>
+                               </form>
+                       ';
+
+        return $fieldRenderingDefinitions;
+    }
+
+    /**
+     * @param array $overrides
+     *
+     * @return array Array of parameters which have to be added to URLs
+     */
+    public function getUrlParameters(array $overrides = null)
+    {
+        return [
+            'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId
+        ];
+    }
+
+    /**
+     * Get attributes for the body tag
+     *
+     * @return string[] Array of body-tag attributes
+     */
+    protected function getBodyTagAttributes()
+    {
+        $parameters = [];
+        $parameters['uid'] = $this->parameters['uid'];
+        $parameters['pid'] = $this->parameters['pid'];
+        $parameters['itemName'] = $this->parameters['itemName'];
+        $parameters['formName'] = $this->parameters['formName'];
+        $parameters['params']['allowedExtensions'] = isset($this->parameters['params']['allowedExtensions']) ? $this->parameters['params']['allowedExtensions'] : '';
+        $parameters['params']['blindLinkOptions'] = isset($this->parameters['params']['blindLinkOptions']) ? $this->parameters['params']['blindLinkOptions'] : '';
+        $parameters['params']['blindLinkFields'] = isset($this->parameters['params']['blindLinkFields']) ? $this->parameters['params']['blindLinkFields']: '';
+        $addPassOnParams = GeneralUtility::implodeArrayForUrl('P', $parameters);
+
+        $attributes = $this->displayedLinkHandler->getBodyTagAttributes();
+        return array_merge(
+            $attributes,
+            [
+                'data-this-script-url' => strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&',
+                'data-url-parameters' => json_encode($this->getUrlParameters()),
+                'data-parameters' => json_encode($this->parameters),
+                'data-add-on-params' => $addPassOnParams,
+                'data-link-attribute-fields' => json_encode($this->linkAttributeFields)
+            ]
+        );
+    }
+
+    /**
+     * Return the ID of current page
+     *
+     * @return int
+     */
+    abstract protected function getCurrentPageId();
+
+    /**
+     * @return array
+     */
+    public function getParameters()
+    {
+        return $this->parameters;
+    }
+
+    /**
+     * Retrieve the configuration
+     *
+     * @return array
+     */
+    public function getConfiguration() {
+        return [];
+    }
+
+    /**
+     * @return string
+     */
+    public function getDisplayedLinkHandlerId()
+    {
+        return $this->displayedLinkHandlerId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getScriptUrl()
+    {
+        return $this->thisScript;
+    }
+
+    /**
+     * @return LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * @return BackendUserAuthentication
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
+}
index 2558dde..1a8f72a 100644 (file)
@@ -77,7 +77,7 @@ class ElementBrowserController
     }
 
     /**
-     * Injects the request object for the current request or subrequest
+     * Injects the request object for the current request or sub-request
      * As this controller goes only through the main() method, it is rather simple for now
      *
      * @param ServerRequestInterface $request the current request
@@ -88,7 +88,7 @@ class ElementBrowserController
     {
         // Fallback for old calls, which use mode "wizard" or "rte" for link selection
         if ($this->mode === 'wizard' || $this->mode === 'rte') {
-            return $response->withStatus(303)->withHeader('Location', BackendUtility::getModuleUrl('wizard_link_browser', $_GET, false, true));
+            return $response->withStatus(303)->withHeader('Location', BackendUtility::getModuleUrl('wizard_link', $_GET, false, true));
         }
 
         $response->getBody()->write($this->main());
diff --git a/typo3/sysext/recordlist/Classes/Controller/LinkBrowserController.php b/typo3/sysext/recordlist/Classes/Controller/LinkBrowserController.php
deleted file mode 100644 (file)
index ac1d688..0000000
+++ /dev/null
@@ -1,727 +0,0 @@
-<?php
-namespace TYPO3\CMS\Recordlist\Controller;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\ResponseInterface;
-use TYPO3\CMS\Backend\Routing\Router;
-use TYPO3\CMS\Backend\Routing\UriBuilder;
-use TYPO3\CMS\Backend\Template\DocumentTemplate;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Page\PageRenderer;
-use TYPO3\CMS\Core\Service\DependencyOrderingService;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
-use TYPO3\CMS\Lang\LanguageService;
-use TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface;
-
-/**
- * Script class for the Link Browser window.
- */
-class LinkBrowserController
-{
-    /**
-     * @var DocumentTemplate
-     */
-    protected $doc;
-
-    /**
-     * @var array
-     */
-    protected $parameters;
-
-    /**
-     * URL of current request
-     *
-     * @var string
-     */
-    protected $thisScript = '';
-
-    /**
-     * @var LinkHandlerInterface[]
-     */
-    protected $linkHandlers = [];
-
-    /**
-     * @var string
-     */
-    protected $currentLink = '';
-
-    /**
-     * Link handler responsible for the current active link
-     *
-     * @var LinkHandlerInterface $currentLinkHandler
-     */
-    protected $currentLinkHandler;
-
-    /**
-     * The ID of the currently active link handler
-     *
-     * @var string
-     */
-    protected $currentLinkHandlerId;
-
-    /**
-     * Link handler to be displayed
-     *
-     * @var LinkHandlerInterface $displayedLinkHandler
-     */
-    protected $displayedLinkHandler;
-
-    /**
-     * The ID of the displayed link handler
-     *
-     * This is read from the 'act' GET parameter
-     *
-     * @var string
-     */
-    protected $displayedLinkHandlerId = '';
-
-    /**
-     * List of available link attribute fields
-     *
-     * @var string[]
-     */
-    protected $linkAttributeFields = [];
-
-    /**
-     * Values of the link attributes
-     *
-     * @var string[]
-     */
-    protected $linkAttributeValues = [];
-
-    /**
-     * @var array
-     */
-    protected $hookObjects = [];
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        $this->initHookObjects();
-        $this->init();
-    }
-
-    /**
-     * Initialize the controller
-     *
-     * @return void
-     */
-    protected function init()
-    {
-        $this->getLanguageService()->includeLLFile('EXT:lang/locallang_browse_links.xlf');
-    }
-
-    /**
-     * Initialize hook objects implementing the interface
-     *
-     * @throws \UnexpectedValueException
-     * @return void
-     */
-    protected function initHookObjects()
-    {
-        if (
-            isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks'])
-            && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks'])
-        ) {
-            $hooks = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies(
-                $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['LinkBrowser']['hooks']
-            );
-            foreach ($hooks as $key => $hook) {
-                $this->hookObjects[] = GeneralUtility::makeInstance($hook['handler']);
-            }
-        }
-    }
-
-    /**
-     * Injects the request object for the current request or subrequest
-     * As this controller goes only through the main() method, it is rather simple for now
-     *
-     * @param ServerRequestInterface $request the current request
-     * @param ResponseInterface $response the prepared response object
-     * @return ResponseInterface the response with the content
-     */
-    public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
-    {
-        $this->determineScriptUrl($request);
-        $this->initVariables($request);
-        $this->loadLinkHandlers();
-        $this->initCurrentUrl();
-
-        $menuData = $this->buildMenuArray();
-        $renderLinkAttributeFields = $this->renderLinkAttributeFields();
-        $browserContent = $this->displayedLinkHandler->render($request);
-
-        $this->initDocumentTemplate();
-        $content = $this->doc->startPage('Link Browser');
-        $content .= $this->doc->getFlashMessages();
-
-        if ($this->currentLink) {
-            $content .= '<!-- Print current URL -->
-                               <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
-                                       <tr>
-                                               <td>' . $this->getLanguageService()->getLL('currentLink', true) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . '</td>
-                                       </tr>
-                               </table>';
-        }
-        $content .= $this->doc->getTabMenuRaw($menuData);
-        $content .= $renderLinkAttributeFields;
-
-        $content .= '<div class="linkBrowser-tabContent">' . $browserContent . '</div>';
-        $content .= $this->doc->endPage();
-
-        $response->getBody()->write($this->doc->insertStylesAndJS($content));
-        return $response;
-    }
-
-    /**
-     * Sets the script url depending on being a module or script request
-     *
-     * @param ServerRequestInterface $request
-     *
-     * @throws \TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException
-     * @throws \TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException
-     */
-    protected function determineScriptUrl(ServerRequestInterface $request)
-    {
-        if ($routePath = $request->getQueryParams()['route']) {
-            $router = GeneralUtility::makeInstance(Router::class);
-            $route = $router->match($routePath);
-            $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-            $this->thisScript = (string)$uriBuilder->buildUriFromRoute($route->getOption('_identifier'));
-        } elseif ($moduleName = $request->getQueryParams()['M']) {
-            $this->thisScript = BackendUtility::getModuleUrl($moduleName);
-        } else {
-            $this->thisScript = GeneralUtility::getIndpEnv('SCRIPT_NAME');
-        }
-    }
-
-    /**
-     * @param ServerRequestInterface $request
-     */
-    protected function initVariables(ServerRequestInterface $request)
-    {
-        $queryParams = $request->getQueryParams();
-        $act = isset($queryParams['act']) ? $queryParams['act'] : '';
-        // @deprecated since CMS 7, remove with CMS 8
-        if (strpos($act, '|')) {
-            GeneralUtility::deprecationLog('Using multiple values for the "act" parameter in the link wizard is deprecated. Only a single value is allowed. Values were: ' . $act);
-            $act = array_shift(explode('|', $act));
-        }
-        $this->displayedLinkHandlerId = $act;
-        $this->parameters = isset($queryParams['P']) ? $queryParams['P'] : [];
-        $this->linkAttributeValues = isset($queryParams['linkAttributes']) ? $queryParams['linkAttributes'] : [];
-        $this->currentLink = isset($this->parameters['currentValue']) ? trim($this->parameters['currentValue']) : '';
-    }
-
-    /**
-     * @return void
-     * @throws \UnexpectedValueException
-     */
-    protected function loadLinkHandlers()
-    {
-        $linkHandlers = $this->getLinkHandlers();
-        if (empty($linkHandlers)) {
-            throw new \UnexpectedValueException('No link handlers are configured. Check page TSconfig TCEMAIN.linkHandlers.', 1442787911);
-        }
-
-        $lang = $this->getLanguageService();
-        foreach ($linkHandlers as $identifier => $configuration) {
-            $identifier = rtrim($identifier, '.');
-            /** @var LinkHandlerInterface $handler */
-            $handler = GeneralUtility::makeInstance($configuration['handler']);
-            $handler->initialize(
-                $this,
-                $identifier,
-                isset($configuration['configuration.']) ? $configuration['configuration.'] : []
-            );
-
-            $this->linkHandlers[$identifier] = [
-                'handlerInstance' => $handler,
-                'label' => $lang->sL($configuration['label'], true),
-                'displayBefore' => isset($configuration['displayBefore']) ? GeneralUtility::trimExplode(',', $configuration['displayBefore']) : [],
-                'displayAfter' => isset($configuration['displayAfter']) ? GeneralUtility::trimExplode(',', $configuration['displayAfter']) : [],
-                'scanBefore' => isset($configuration['scanBefore']) ? GeneralUtility::trimExplode(',', $configuration['scanBefore']) : [],
-                'scanAfter' => isset($configuration['scanAfter']) ? GeneralUtility::trimExplode(',', $configuration['scanAfter']) : [],
-                'addParams' => isset($configuration['addParams']) ? $configuration['addParams'] : '',
-            ];
-        }
-    }
-
-    /**
-     * Reads the configured link handlers from page TSconfig
-     *
-     * @return array
-     */
-    protected function getLinkHandlers()
-    {
-        $pageTSconfig = BackendUtility::getPagesTSconfig($this->getCurrentPageId());
-        $pageTSconfig = $this->getBackendUser()->getTSConfig('TCEMAIN.linkHandler.', $pageTSconfig);
-        $linkHandlers = (array)$pageTSconfig['properties'];
-
-        foreach ($this->hookObjects as $hookObject) {
-            if (method_exists($hookObject, 'modifyLinkHandlers')) {
-                $linkHandlers = $hookObject->modifyLinkHandlers($linkHandlers, $this->currentLink);
-            }
-        }
-
-        return $linkHandlers;
-    }
-
-    /**
-     * Initialize $this->currentLink and $this->currentLinkHandler
-     *
-     * @return void
-     */
-    protected function initCurrentUrl()
-    {
-        if (!$this->currentLink) {
-            return;
-        }
-
-        $currentLinkParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($this->currentLink);
-        $currentLinkParts['params'] = $currentLinkParts['additionalParams'];
-        unset($currentLinkParts['additionalParams']);
-
-        $orderedHandlers = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($this->linkHandlers, 'scanBefore', 'scanAfter');
-
-        // find responsible handler for current link
-        foreach ($orderedHandlers as $key => $configuration) {
-            /** @var LinkHandlerInterface $handler */
-            $handler = $configuration['handlerInstance'];
-            if ($handler->canHandleLink($currentLinkParts)) {
-                $this->currentLinkHandler = $handler;
-                $this->currentLinkHandlerId = $key;
-                break;
-            }
-        }
-        // reset the link if we have no handler for it
-        if (!$this->currentLinkHandler) {
-            $this->currentLink = '';
-        }
-
-        unset($currentLinkParts['url']);
-        // overwrite any preexisting
-        foreach ($currentLinkParts as $key => $part) {
-            $this->linkAttributeValues[$key] = $part;
-        }
-    }
-
-    /**
-     * Initialize document template object
-     *
-     *  @return void
-     */
-    protected function initDocumentTemplate()
-    {
-        $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
-        $this->doc->bodyTagId = 'typo3-browse-links-php';
-
-        if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(true)) {
-            $this->parameters['fieldChangeFunc'] = array();
-        }
-        unset($this->parameters['fieldChangeFunc']['alert']);
-        $update = [];
-        foreach ($this->parameters['fieldChangeFunc'] as $v) {
-            $update[] = 'parent.opener.' . $v;
-        }
-        $inlineJS = implode(LF, $update);
-
-        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-        $pageRenderer->loadJquery();
-        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/LinkBrowser', 'function(LinkBrowser) {
-                       LinkBrowser.updateFunctions = function() {' . $inlineJS . '};
-               }');
-
-        foreach ($this->getBodyTagAttributes() as $attributeName => $value) {
-            $this->doc->bodyTagAdditions .= ' ' . $attributeName . '="' . htmlspecialchars($value) . '"';
-        }
-
-        // Finally, add the accumulated JavaScript to the template object:
-        // also unset the default jumpToUrl() function before
-        unset($this->doc->JScodeArray['jumpToUrl']);
-    }
-
-    /**
-     * Returns an array definition of the top menu
-     *
-     * @return mixed[][]
-     */
-    protected function buildMenuArray()
-    {
-        $allowedItems = $this->getAllowedItems();
-        if ($this->displayedLinkHandlerId && !in_array($this->displayedLinkHandlerId, $allowedItems, true)) {
-            $this->displayedLinkHandlerId = '';
-        }
-
-        $allowedHandlers = array_flip($allowedItems);
-        $menuDef = array();
-        foreach ($this->linkHandlers as $identifier => $configuration) {
-            if (!isset($allowedHandlers[$identifier])) {
-                continue;
-            }
-
-            /** @var LinkHandlerInterface $handlerInstance */
-            $handlerInstance = $configuration['handlerInstance'];
-            $isActive = $this->displayedLinkHandlerId === $identifier || !$this->displayedLinkHandlerId && $handlerInstance === $this->currentLinkHandler;
-            if ($isActive) {
-                $this->displayedLinkHandler = $handlerInstance;
-                if (!$this->displayedLinkHandlerId) {
-                    $this->displayedLinkHandlerId = $this->currentLinkHandlerId;
-                }
-            }
-
-            if ($configuration['addParams']) {
-                $addParams = $configuration['addParams'];
-            } else {
-                $parameters = GeneralUtility::implodeArrayForUrl('', $this->getUrlParameters(['act' => $identifier]));
-                $addParams = 'onclick="jumpToUrl(' . GeneralUtility::quoteJSvalue('?' . ltrim($parameters, '&')) . ');return false;"';
-            }
-            $menuDef[$identifier] = [
-                'isActive' => $isActive,
-                'label' => $configuration['label'],
-                'url' => '#',
-                'addParams' => $addParams,
-                'before' => $configuration['displayBefore'],
-                'after' => $configuration['displayAfter']
-            ];
-        }
-
-        $menuDef = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies($menuDef);
-
-        // if there is no active tab
-        if (!$this->displayedLinkHandler) {
-            // empty the current link
-            $this->currentLink = '';
-            $this->currentLinkHandler = null;
-            $this->currentLinkHandler = '';
-            // select first tab
-            reset($menuDef);
-            $this->displayedLinkHandlerId = key($menuDef);
-            $this->displayedLinkHandler = $this->linkHandlers[$this->displayedLinkHandlerId]['handlerInstance'];
-            $menuDef[$this->displayedLinkHandlerId]['isActive'] = true;
-        }
-
-        return $menuDef;
-    }
-
-    /**
-     * Get the allowed items or tabs
-     *
-     * @return string[]
-     */
-    protected function getAllowedItems()
-    {
-        $allowedItems = array_keys($this->linkHandlers);
-
-        foreach ($this->hookObjects as $hookObject) {
-            if (method_exists($hookObject, 'modifyAllowedItems')) {
-                $allowedItems = $hookObject->modifyAllowedItems($allowedItems, $this->currentLink);
-            }
-        }
-
-        // Initializing the action value, possibly removing blinded values etc:
-        $blindLinkOptions = isset($this->parameters['params']['blindLinkOptions'])
-            ? GeneralUtility::trimExplode(',', $this->parameters['params']['blindLinkOptions'])
-            : [];
-        $allowedItems = array_diff($allowedItems, $blindLinkOptions);
-
-        return $allowedItems;
-    }
-
-    /**
-     * Get the allowed link attributes
-     *
-     * @return string[]
-     */
-    protected function getAllowedLinkAttributes()
-    {
-        $allowedLinkAttributes = $this->displayedLinkHandler->getLinkAttributes();
-
-        // Removing link fields if configured
-        $blindLinkFields = isset($this->parameters['params']['blindLinkFields'])
-            ? GeneralUtility::trimExplode(',', $this->parameters['params']['blindLinkFields'], true)
-            : [];
-        $allowedLinkAttributes = array_diff($allowedLinkAttributes, $blindLinkFields);
-
-        return $allowedLinkAttributes;
-    }
-
-    /**
-     * Renders the link attributes for the selected link handler
-     *
-     * @return string
-     */
-    public function renderLinkAttributeFields()
-    {
-        $fieldRenderingDefinitions = $this->getLinkAttributeFieldDefinitions();
-        $this->linkAttributeFields = $this->getAllowedLinkAttributes();
-
-        $content = '';
-        foreach ($this->linkAttributeFields as $attribute) {
-            $content .= $fieldRenderingDefinitions[$attribute];
-        }
-
-        // add update button if appropriate
-        if ($this->currentLink && $this->displayedLinkHandler === $this->currentLinkHandler && $this->currentLinkHandler->isUpdateSupported()) {
-            $content .= '
-                               <form action="" name="lparamsform" id="lparamsform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
-                                       <tr><td>
-                                               <input class="btn btn-default t3-js-linkCurrent" type="submit" value="' . $this->getLanguageService()->getLL('update', true) . '" />
-                                       </td></tr>
-                                       </table>
-                               </form><br /><br />';
-        }
-
-        return $content;
-    }
-
-    /**
-     * Create an array of link attribute field rendering definitions
-     *
-     * @return string[]
-     */
-    protected function getLinkAttributeFieldDefinitions()
-    {
-        $lang = $this->getLanguageService();
-
-        $fieldRenderingDefinitions = [];
-        $fieldRenderingDefinitions['target'] = '
-                       <!--
-                               Selecting target for link:
-                       -->
-                               <form action="" name="ltargetform" id="ltargetform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTarget">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('target', true) . ':</td>
-                                                       <td>
-                                                               <input type="text" name="ltarget" id="linkTarget" value="' . htmlspecialchars($this->linkAttributeValues['target']) . '" />
-                                                               <select name="ltarget_type" id="targetPreselect">
-                                                                       <option value=""></option>
-                                                                       <option value="_top">' . $lang->getLL('top', true) . '</option>
-                                                                       <option value="_blank">' . $lang->getLL('newWindow', true) . '</option>
-                                                               </select>
-                                                       </td>
-                                               </tr>
-                                       </table>
-                               </form>';
-
-        $fieldRenderingDefinitions['title'] = '
-                               <!--
-                                       Selecting title for link:
-                               -->
-                               <form action="" name="ltitleform" id="ltitleform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkTitle">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('title', true) . '</td>
-                                                       <td><input type="text" name="ltitle" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['title']) . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-
-        $fieldRenderingDefinitions['class'] = '
-                               <!--
-                                       Selecting class for link:
-                               -->
-                               <form action="" name="lclassform" id="lclassform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkClass">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('class', true) . '</td>
-                                                       <td><input type="text" name="lclass" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['class']) . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-
-        $fieldRenderingDefinitions['params'] = '
-                               <!--
-                                       Selecting params for link:
-                               -->
-                               <form action="" name="lparamsform" id="lparamsform">
-                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkParams">
-                                               <tr>
-                                                       <td style="width: 96px;">' . $lang->getLL('params', true) . '</td>
-                                                       <td><input type="text" name="lparams" class="typo3-link-input" value="' . htmlspecialchars($this->linkAttributeValues['params']) . '" /></td>
-                                               </tr>
-                                       </table>
-                               </form>
-                       ';
-
-        return $fieldRenderingDefinitions;
-    }
-
-    /**
-     * @param array $overrides
-     *
-     * @return array Array of parameters which have to be added to URLs
-     */
-    public function getUrlParameters(array $overrides = null)
-    {
-        return [
-            'act' => isset($overrides['act']) ? $overrides['act'] : $this->displayedLinkHandlerId
-        ];
-    }
-
-    /**
-     * @return string[] Array of body-tag attributes
-     */
-    protected function getBodyTagAttributes()
-    {
-        $parameters = [];
-        $parameters['uid'] = $this->parameters['uid'];
-        $parameters['pid'] = $this->parameters['pid'];
-        $parameters['itemName'] = $this->parameters['itemName'];
-        $parameters['formName'] = $this->parameters['formName'];
-        $parameters['fieldChangeFunc'] = $this->parameters['fieldChangeFunc'];
-        $parameters['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->parameters['fieldChangeFunc']));
-        $parameters['params']['allowedExtensions'] = isset($this->parameters['params']['allowedExtensions']) ? $this->parameters['params']['allowedExtensions'] : '';
-        $parameters['params']['blindLinkOptions'] = isset($this->parameters['params']['blindLinkOptions']) ? $this->parameters['params']['blindLinkOptions'] : '';
-        $parameters['params']['blindLinkFields'] = isset($this->parameters['params']['blindLinkFields']) ? $this->parameters['params']['blindLinkFields']: '';
-        $addPassOnParams = GeneralUtility::implodeArrayForUrl('P', $parameters);
-
-        $attributes = $this->displayedLinkHandler->getBodyTagAttributes();
-        return array_merge(
-            $attributes,
-            [
-                'data-this-script-url' => strpos($this->thisScript, '?') === false ? $this->thisScript . '?' : $this->thisScript . '&',
-                'data-url-parameters' => json_encode($this->getUrlParameters()),
-                'data-parameters' => json_encode($this->parameters),
-                'data-add-on-params' => $addPassOnParams,
-                'data-link-attribute-fields' => json_encode($this->linkAttributeFields)
-            ]
-        );
-    }
-
-    /**
-     * Determines whether submitted field change functions are valid
-     * and are coming from the system and not from an external abuse.
-     *
-     * @param bool $handleFlexformSections Whether to handle flexform sections differently
-     * @return bool Whether the submitted field change functions are valid
-     */
-    protected function areFieldChangeFunctionsValid($handleFlexformSections = false)
-    {
-        $result = false;
-        if (isset($this->parameters['fieldChangeFunc']) && is_array($this->parameters['fieldChangeFunc']) && isset($this->parameters['fieldChangeFuncHash'])) {
-            $matches = array();
-            $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i';
-            $fieldChangeFunctions = $this->parameters['fieldChangeFunc'];
-            // Special handling of flexform sections:
-            // Field change functions are modified in JavaScript, thus the hash is always invalid
-            if ($handleFlexformSections && preg_match($pattern, $this->parameters['itemName'], $matches)) {
-                $originalName = $matches[1];
-                $cleanedName = $matches[2] . $matches[4];
-                foreach ($fieldChangeFunctions as &$value) {
-                    $value = str_replace($originalName, $cleanedName, $value);
-                }
-                unset($value);
-            }
-            $result = $this->parameters['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions));
-        }
-        return $result;
-    }
-
-    /**
-     * Encode a typolink via ajax
-     *
-     * This avoids to implement the encoding functionality again in JS for the browser.
-     *
-     * @param ServerRequestInterface $request
-     * @param ResponseInterface $response
-     * @return ResponseInterface
-     */
-    public static function encodeTypoLink(ServerRequestInterface $request, ResponseInterface $response)
-    {
-        $typoLinkParts = $request->getQueryParams();
-        if (isset($typoLinkParts['params'])) {
-            $typoLinkParts['additionalParams'] = $typoLinkParts['params'];
-            unset($typoLinkParts['params']);
-        }
-
-        $typoLink = GeneralUtility::makeInstance(TypoLinkCodecService::class)->encode($typoLinkParts);
-
-        $response->getBody()->write(json_encode(['typoLink' => $typoLink]));
-        return $response;
-    }
-
-    /**
-     * Return the ID of current page
-     *
-     * @return int
-     */
-    protected function getCurrentPageId()
-    {
-        $pageId = 0;
-        $P = $this->parameters;
-        if (isset($P['pid'])) {
-            $pageId = $P['pid'];
-        } elseif (isset($P['itemName'])) {
-            // parse data[<table>][<uid>]
-            if (preg_match('~data\[([^]]*)\]\[([^]]*)\]~', $P['itemName'], $matches)) {
-                $recordArray = BackendUtility::getRecord($matches['1'], $matches['2']);
-                if (is_array($recordArray)) {
-                    $pageId = $recordArray['pid'];
-                }
-            }
-        }
-        return $pageId;
-    }
-
-    /**
-     * @return array
-     */
-    public function getParameters()
-    {
-        return $this->parameters;
-    }
-
-    /**
-     * @return string
-     */
-    public function getDisplayedLinkHandlerId()
-    {
-        return $this->displayedLinkHandlerId;
-    }
-
-    /**
-     * @return string
-     */
-    public function getScriptUrl()
-    {
-        return $this->thisScript;
-    }
-
-    /**
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-}
index f20c62f..fc477af 100644 (file)
@@ -18,7 +18,7 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Imaging\IconFactory;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Lang\LanguageService;
-use TYPO3\CMS\Recordlist\Controller\LinkBrowserController;
+use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
 
 /**
  * Base class for link handlers
@@ -42,7 +42,7 @@ abstract class AbstractLinkHandler
     protected $updateSupported = true;
 
     /**
-     * @var LinkBrowserController
+     * @var AbstractLinkBrowserController
      */
     protected $linkBrowser;
 
@@ -61,13 +61,13 @@ abstract class AbstractLinkHandler
     /**
      * Initialize the handler
      *
-     * @param LinkBrowserController $linkBrowser
+     * @param AbstractLinkBrowserController $linkBrowser
      * @param string $identifier
      * @param array $configuration Page TSconfig
      *
      * @return void
      */
-    public function initialize(LinkBrowserController $linkBrowser, $identifier, array $configuration)
+    public function initialize(AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration)
     {
         $this->linkBrowser = $linkBrowser;
         $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
@@ -82,6 +82,14 @@ abstract class AbstractLinkHandler
     }
 
     /**
+     * @param string[] $fieldDefinitions Array of link attribute field definitions
+     * @return string[]
+     */
+    public function modifyLinkAttributes(array $fieldDefinitions) {
+        return $fieldDefinitions;
+    }
+
+    /**
      * Return TRUE if the handler supports to update a link.
      *
      * This is useful for e.g. file or page links, when only attributes are changed.
index d4952e3..e46e20d 100644 (file)
@@ -231,10 +231,10 @@ class FileLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
             $out .= '<ul class="list-tree list-tree-root">';
             foreach ($folderContent as $fileOrFolderObject) {
                 list($fileIdentifier, $icon) = $this->renderItem($fileOrFolderObject);
-                $selected = $currentIdentifier === $fileIdentifier ? ' class="active"' : ''; // @todo this class has no styling yet!
+                $selected = $currentIdentifier === $fileIdentifier ? ' class="active"' : '';
                 $out .=
                     '<li' . $selected . '>
-                                               <a href="#" class="t3-js-fileLink" title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" data-file="file:' . htmlspecialchars($fileIdentifier) . '">
+                                               <a href="#" class="t3js-fileLink" title="' . htmlspecialchars($fileOrFolderObject->getName()) . '" data-file="file:' . htmlspecialchars($fileIdentifier) . '">
                                                        ' .    $icon . '
                                                        ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileOrFolderObject->getName(), $titleLen)) . '
                                                </a>
@@ -298,7 +298,7 @@ class FileLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
     public function getBodyTagAttributes()
     {
         return [
-            'data-current-file' => empty($this->linkParts) ? '' : 'file:' . $this->linkParts['url']
+            'data-current-link' => empty($this->linkParts) ? '' : 'file:' . $this->linkParts['url']
         ];
     }
 
index ff4d8d3..6840042 100644 (file)
@@ -15,7 +15,7 @@ namespace TYPO3\CMS\Recordlist\LinkHandler;
  */
 
 use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Recordlist\Controller\LinkBrowserController;
+use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
 
 /**
  * Interface for link handlers displayed in the LinkBrowser
@@ -28,15 +28,21 @@ interface LinkHandlerInterface
     public function getLinkAttributes();
 
     /**
+     * @param string[] $fieldDefinitions Array of link attribute field defintions
+     * @return string[]
+     */
+    public function modifyLinkAttributes(array $fieldDefinitions);
+
+    /**
      * Initialize the handler
      *
-     * @param LinkBrowserController $linkBrowser
+     * @param AbstractLinkBrowserController $linkBrowser
      * @param string $identifier
      * @param array $configuration Page TSconfig
      *
      * @return void
      */
-    public function initialize(LinkBrowserController $linkBrowser, $identifier, array $configuration);
+    public function initialize(AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration);
 
     /**
      * Checks if this is the handler for the given link
index 9e183fb..7a59abd 100644 (file)
@@ -43,8 +43,13 @@ class MailLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
     public function __construct()
     {
         parent::__construct();
-        // remove unsupported link attribute
-        unset($this->linkAttributes[array_search('target', $this->linkAttributes, true)]);
+        // remove unsupported link attributes
+        foreach (['target', 'rel'] as $attribute) {
+            $position = array_search($attribute, $this->linkAttributes, true);
+            if ($position !== false) {
+                unset($this->linkAttributes[$position]);
+            }
+        }
     }
 
     /**
index 039edf3..ff865ca 100644 (file)
@@ -201,7 +201,7 @@ class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
                                                        ' . $icon . '
                                                </span>
                                                <span class="list-tree-title">
-                                                       <a href="#" class="t3-js-pageLink" data-id="' . (int)$expPageId . '" data-anchor="#' . (int)$row['uid'] . '">
+                                                       <a href="#" class="t3js-pageLink" data-id="' . (int)$expPageId . '" data-anchor="#' . (int)$row['uid'] . '">
                                                                ' . htmlspecialchars(BackendUtility::getRecordTitle('tt_content', $row, true)) . '
                                                        </a>
                                                </span>
@@ -271,7 +271,7 @@ class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
             return [];
         }
         return [
-            'data-current-link' => $this->linkParts['pageid'] . '#' . $this->linkParts['anchor']
+            'data-current-link' => $this->linkParts['pageid'] . ($this->linkParts['anchor'] !== '' ? '#' . $this->linkParts['anchor'] : '')
         ];
     }
 
@@ -309,6 +309,29 @@ class PageLinkHandler extends AbstractLinkHandler implements LinkHandlerInterfac
     }
 
     /**
+     * @param string[] $fieldDefinitions Array of link attribute field definitions
+     * @return string[]
+     */
+    public function modifyLinkAttributes(array $fieldDefinitions) {
+        $configuration = $this->linkBrowser->getConfiguration();
+        if (!empty($configuration['pageIdSelector.']['enabled'])) {
+            $fieldDefinitions['pageIdSelector'] = '
+                               <tr>
+                                       <td>
+                                               <label>
+                                                       ' . $this->getLanguageService()->getLL('page_id', true) . ':
+                                               </label>
+                                       </td>
+                                       <td colspan="3">
+                                               <input type="text" size="6" name="luid" id="luid" /> <input class="btn btn-default t3js-pageLink" type="submit" value="'
+            . $this->getLanguageService()->getLL('setLink', true) . '" />
+                                       </td>
+                               </tr>';
+        }
+        return $fieldDefinitions;
+    }
+
+    /**
      * @return DatabaseConnection
      */
     protected function getDatabaseConnection()
index 5f27a8d..3908ed8 100644 (file)
@@ -30,17 +30,15 @@ class DummyLinkParameterProvider implements LinkParameterProviderInterface
     protected $thisScript;
 
     /**
-     * @param string $mode
-     * @param string $act
+     * @param string[] $parameters
      * @param string $thisScript
      */
-    public function __construct($mode, $act, $thisScript)
+    public function __construct(array $parameters, $thisScript)
     {
-        if ($mode) {
-            $this->parameters['mode'] = $mode;
-        }
-        if ($act) {
-            $this->parameters['act'] = $act;
+        foreach ($parameters as $name => $value) {
+            if ($value) {
+                $this->parameters[$name] = $value;
+            }
         }
         $this->thisScript = $thisScript;
     }
diff --git a/typo3/sysext/recordlist/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/recordlist/Configuration/Backend/AjaxRoutes.php
deleted file mode 100644 (file)
index b05e2df..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-/**
- * Definitions for routes provided by EXT:recordlist
- */
-return [
-
-    'link_browser_encodeTypoLink' => [
-        'path' => '/linkBrowser/encodeTypoLink',
-        'target' => \TYPO3\CMS\Recordlist\Controller\LinkBrowserController::class . '::encodeTypoLink',
-        'access' => 'public'
-    ],
-
-];
index cf1abd7..e9fbcd4 100644 (file)
@@ -8,9 +8,4 @@ return [
         'path' => '/wizard/record/browse',
         'target' => \TYPO3\CMS\Recordlist\Controller\ElementBrowserController::class . '::mainAction'
     ],
-
-    'wizard_link_browser' => [
-        'path' => '/wizard/link/browse',
-        'target' => \TYPO3\CMS\Recordlist\Controller\LinkBrowserController::class . '::mainAction'
-    ]
 ];
index a3c559e..b544076 100644 (file)
@@ -105,8 +105,8 @@ define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Lega
                        BrowseFiles.File.insertElement('file_' + $(this).data('fileIndex'), $(this).data('close'));
                });
 
-               $('#t3-js-importSelection').on('click', BrowseFiles.Selector.handle);
-               $('#t3-js-toggleSelection').on('click', BrowseFiles.Selector.toggle);
+               $('#t3js-importSelection').on('click', BrowseFiles.Selector.handle);
+               $('#t3js-toggleSelection').on('click', BrowseFiles.Selector.toggle);
        });
 
        return BrowseFiles;
index 2447de7..ba00b0e 100644 (file)
@@ -27,7 +27,7 @@ define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Moda
                        ElementBrowser.insertElement('', folderId, 'folder', folderId, folderId, '', '', '', close);
                });
 
-               $('.t3-js-folderIdError').on('click', function (event) {
+               $('.t3js-folderIdError').on('click', function (event) {
                        event.preventDefault();
                        Modal.confirm('', $(this).data('message'), opener.TYPO3.Severity.error, [], []);
                });
index 1a0441d..1436c25 100644 (file)
@@ -34,9 +34,10 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/LegacyT
        FileLinkHandler.linkFile = function(event) {
                event.preventDefault();
 
-               LinkBrowser.updateValueInMainForm($(this).data('file'));
-
-               close();
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction($(this).data('file'));
        };
 
        /**
@@ -46,10 +47,10 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/LegacyT
        FileLinkHandler.linkCurrent = function(event) {
                event.preventDefault();
 
-               LinkBrowser.updateValueInMainForm(FileLinkHandler.currentLink);
-
-               close();
-
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction(FileLinkHandler.currentLink);
        };
 
        Tree.ajaxID = 'sc_alt_file_navframe_expandtoggle';
@@ -57,8 +58,8 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/LegacyT
        $(function() {
                FileLinkHandler.currentLink = $('body').data('currentLink');
 
-               $('a.t3-js-fileLink').on('click', FileLinkHandler.linkFile);
-               $('input.t3-js-linkCurrent').on('click', FileLinkHandler.linkCurrent);
+               $('a.t3js-fileLink').on('click', FileLinkHandler.linkFile);
+               $('input.t3js-linkCurrent').on('click', FileLinkHandler.linkCurrent);
        });
 
        return FileLinkHandler;
index 9ad6d2c..6bc93b2 100644 (file)
@@ -20,7 +20,7 @@ define(['jquery'], function($) {
 
        /**
         *
-        * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, updateFunctions: null}}
+        * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, additionalLinkAttributes: {}, finalizeFunction: null}}
         * @exports TYPO3/CMS/Recordlist/LinkBrowser
         */
        var LinkBrowser = {
@@ -29,21 +29,8 @@ define(['jquery'], function($) {
                parameters: {},
                addOnParams: '',
                linkAttributeFields: [],
-               updateFunctions: null // those are set in the module initializer function in PHP
-       };
-
-       /**
-        * Return reference to parent's form element
-        *
-        * @returns {Element}
-        */
-       LinkBrowser.checkReference = function () {
-               var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]';
-               if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) {
-                       return window.opener.document.querySelector(selector);
-               } else {
-                       close();
-               }
+               additionalLinkAttributes: {},
+               finalizeFunction: null // receives the value of the selected element as parameter (e.g. "page:<pageUid>" or "file:<uid>", etc
        };
 
        /**
@@ -59,46 +46,15 @@ define(['jquery'], function($) {
                                attributeValues[fieldName] = val;
                        }
                });
+               $.extend(attributeValues, LinkBrowser.additionalLinkAttributes);
                return attributeValues;
        };
 
        /**
-        * Save the current link back to the opener
-        *
-        * @param {String} input
-        */
-       LinkBrowser.updateValueInMainForm = function(input) {
-               var field = LinkBrowser.checkReference();
-               if (field) {
-                       var attributeValues = LinkBrowser.getLinkAttributeValues();
-
-                       // encode link on server
-                       attributeValues.url = input;
-
-                       $.ajax({
-                               url: TYPO3.settings.ajaxUrls['link_browser_encodeTypoLink'],
-                               data: attributeValues,
-                               method: 'GET',
-                               async: false,
-                               success: function(data) {
-                                       if (data.typoLink) {
-                                               field.value = data.typoLink;
-                                               if (typeof field.onchange === 'function') {
-                                                       field.onchange();
-                                               }
-
-                                               LinkBrowser.updateFunctions();
-                                       }
-                               }
-                       });
-               }
-       };
-
-       /**
         *
         */
        LinkBrowser.loadTarget = function() {
-               $('#linkTarget').val($(this).val());
+               $('.t3js-linkTarget').val($(this).val());
                this.selectedIndex = 0;
        };
 
@@ -127,6 +83,10 @@ define(['jquery'], function($) {
                return '&' + str.join("&");
        };
 
+       LinkBrowser.setAdditionalLinkAttribute = function(name, value) {
+               LinkBrowser.additionalLinkAttributes[name] = value;
+       };
+
        $(function() {
                var data = $('body').data();
 
@@ -136,7 +96,7 @@ define(['jquery'], function($) {
                LinkBrowser.addOnParams = data.addOnParams;
                LinkBrowser.linkAttributeFields = data.linkAttributeFields;
 
-               $('#targetPreselect').on('change', LinkBrowser.loadTarget);
+               $('.t3js-targetPreselect').on('change', LinkBrowser.loadTarget);
        });
 
        /**
index 5bf21b9..97b349f 100644 (file)
@@ -25,29 +25,24 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser)
         */
        var MailLinkHandler = {};
 
-       /**
-        *
-        * @param {Event} event
-        */
-       MailLinkHandler.link = function(event) {
-               event.preventDefault();
-
-               var value = $(this).find('[name="lemail"]').val();
-               if (value === "mailto:") {
-                       return;
-               }
-
-               while (value.substr(0, 7) === "mailto:") {
-                       value = value.substr(7);
-               }
-
-               LinkBrowser.updateValueInMainForm(value);
-
-               close();
-       };
-
        $(function() {
-               $('#lmailform').on('submit', MailLinkHandler.link);
+               $('#lmailform').on('submit', function(event) {
+                       event.preventDefault();
+
+                       var value = $(this).find('[name="lemail"]').val();
+                       if (value === 'mailto:') {
+                               return;
+                       }
+
+                       while (value.substr(0, 7) === 'mailto:') {
+                               value = value.substr(7);
+                       }
+
+                       if (!LinkBrowser.finalizeFunction) {
+                               throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+                       }
+                       LinkBrowser.finalizeFunction('mailto:' + value);
+               });
        });
 
        return MailLinkHandler;
index c2421c4..0d69a8a 100644 (file)
@@ -36,28 +36,50 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser)
 
                var id = $(this).data('id');
                var anchor = $(this).data('anchor');
-               LinkBrowser.updateValueInMainForm(id + (anchor ? anchor : ""));
 
-               close();
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction('page:' + id + (anchor ? anchor : ''));
        };
 
        /**
         *
         * @param {Event} event
         */
-       PageLinkHandler.linkCurrent = function(event) {
+       PageLinkHandler.linkPageByTextfield = function(event) {
                event.preventDefault();
 
-               LinkBrowser.updateValueInMainForm(PageLinkHandler.currentLink);
+               var value = $('#luid').val();
+               if (!value) {
+                       return;
+               }
+
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction('page:' + value);
+       };
+
+       /**
+        *
+        * @param {Event} event
+        */
+       PageLinkHandler.linkCurrent = function(event) {
+               event.preventDefault();
 
-               close();
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction('page:' + PageLinkHandler.currentLink);
        };
 
        $(function() {
                PageLinkHandler.currentLink = $('body').data('currentLink');
 
-               $('a.t3-js-pageLink').on('click', PageLinkHandler.linkPage);
-               $('input.t3-js-linkCurrent').on('click', PageLinkHandler.linkCurrent);
+               $('a.t3js-pageLink').on('click', PageLinkHandler.linkPage);
+               $('input.t3js-linkCurrent').on('click', PageLinkHandler.linkCurrent);
+               $('input.t3js-pageLink').on('click', PageLinkHandler.linkPageByTextfield);
        });
 
        return PageLinkHandler;
index 79fe50e..2fe35de 100644 (file)
@@ -37,13 +37,12 @@ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser)
                        return;
                }
 
-               if (value.substr(0, 7) === "http://") {
-                       value = value.substr(7);
-               }
-
-               LinkBrowser.updateValueInMainForm(value);
+               LinkBrowser.setAdditionalLinkAttribute('data-htmlarea-external', '1');
 
-               close();
+               if (!LinkBrowser.finalizeFunction) {
+                       throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+               }
+               LinkBrowser.finalizeFunction(value);
        };
 
        $(function() {
diff --git a/typo3/sysext/rtehtmlarea/Classes/BrowseLinks.php b/typo3/sysext/rtehtmlarea/Classes/BrowseLinks.php
deleted file mode 100644 (file)
index 14f98e7..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-<?php
-namespace TYPO3\CMS\Rtehtmlarea;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Lang\LanguageService;
-use TYPO3\CMS\Recordlist\Browser\ElementBrowser;
-
-/**
- * Script class for the Element Browser window.
- */
-class BrowseLinks extends ElementBrowser
-{
-    /**
-     * @var array
-     */
-    public $additionalAttributes = array();
-
-    /**
-     * @var array
-     */
-    public $anchorTypes = array('page', 'url', 'file', 'mail');
-
-    /**
-     * @var array
-     */
-    public $classesAnchorDefault = array();
-
-    /**
-     * @var array
-     */
-    public $classesAnchorDefaultTitle = array();
-
-    /**
-     * @var array
-     */
-    public $classesAnchorClassTitle = array();
-
-    /**
-     * @var array
-     */
-    public $classesAnchorDefaultTarget = array();
-
-    /**
-     * @var array
-     */
-    public $classesAnchorJSOptions = array();
-
-    /**
-     * @var
-     */
-    protected $defaultLinkTarget;
-
-    /**
-     * Initialize the current or default values of the link attributes
-     *
-     * @return void
-     */
-    protected function initLinkAttributes()
-    {
-        // Initializing the class value
-        $this->setClass = isset($this->curUrlArray['class']) ? $this->curUrlArray['class'] : '';
-        // Processing the classes configuration
-        if (!empty($this->buttonConfig['properties.']['class.']['allowedClasses'])) {
-            $classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], true);
-            // Collecting allowed classes and configured default values
-            $classesAnchor = array();
-            $classesAnchor['all'] = array();
-            $titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
-                || $this->buttonConfig[$this->act . '.']['properties.']['title.']['readOnly'];
-            if (is_array($this->RTEProperties['classesAnchor.'])) {
-                foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
-                    if (in_array($conf['class'], $classesAnchorArray)) {
-                        $classesAnchor['all'][] = $conf['class'];
-                        if (in_array($conf['type'], $this->anchorTypes)) {
-                            $classesAnchor[$conf['type']][] = $conf['class'];
-                            if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
-                                $this->classesAnchorDefault[$conf['type']] = $conf['class'];
-                                if ($conf['titleText']) {
-                                    $this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText']));
-                                }
-                                if (isset($conf['target'])) {
-                                    $this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
-                                }
-                            }
-                        }
-                        if ($titleReadOnly && $conf['titleText']) {
-                            $this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText'])));
-                        }
-                    }
-                }
-            }
-            // Constructing the class selector options
-            foreach ($this->anchorTypes as $anchorType) {
-                $currentClass = $this->curUrlInfo['act'] === $anchorType ? $this->curUrlArray['class'] : '';
-                foreach ($classesAnchorArray as $class) {
-                    if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$anchorType]) && in_array($class, $classesAnchor[$anchorType])) {
-                        $selected = '';
-                        if ($currentClass == $class || !$currentClass && $this->classesAnchorDefault[$anchorType] == $class) {
-                            $selected = 'selected="selected"';
-                        }
-                        $classLabel = !empty($this->RTEProperties['classes.'][$class . '.']['name'])
-                            ? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0)
-                            : $class;
-                        $classStyle = !empty($this->RTEProperties['classes.'][$class . '.']['value'])
-                            ? $this->RTEProperties['classes.'][$class . '.']['value']
-                            : '';
-                        $this->classesAnchorJSOptions[$anchorType] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
-                    }
-                }
-                if ($this->classesAnchorJSOptions[$anchorType] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->act . '.']['properties.']['class.']['required'])) {
-                    $selected = '';
-                    if (!$this->setClass && !$this->classesAnchorDefault[$anchorType]) {
-                        $selected = 'selected="selected"';
-                    }
-                    $this->classesAnchorJSOptions[$anchorType] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$anchorType];
-                }
-            }
-        }
-        // Initializing the title value
-        $this->setTitle = isset($this->curUrlArray['title']) ? $this->curUrlArray['title'] : '';
-        // Initializing the target value
-        $this->setTarget = isset($this->curUrlArray['target']) ? $this->curUrlArray['target'] : '';
-        // Default target
-        $this->defaultLinkTarget = $this->classesAnchorDefault[$this->act] && $this->classesAnchorDefaultTarget[$this->act]
-            ? $this->classesAnchorDefaultTarget[$this->act]
-            : (isset($this->buttonConfig[$this->act . '.']['properties.']['target.']['default'])
-                ? $this->buttonConfig[$this->act . '.']['properties.']['target.']['default']
-                : (isset($this->buttonConfig['properties.']['target.']['default'])
-                    ? $this->buttonConfig['properties.']['target.']['default']
-                    : ''));
-        // Initializing additional attributes
-        if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
-            $addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], true);
-            foreach ($addAttributes as $attribute) {
-                $this->additionalAttributes[$attribute] = isset($this->curUrlArray[$attribute]) ? $this->curUrlArray[$attribute] : '';
-            }
-        }
-    }
-
-    /**
-     * Generate JS code to be used on the link insert/modify dialogue
-     *
-     * @return string the generated JS code
-     */
-    public function getJSCode()
-    {
-        // BEGIN accumulation of header JavaScript:
-        $JScode = '';
-        // Attributes setting functions
-        $JScode .= '
-                       function browse_links_setHref(value) {
-                               cur_href=value;
-                               add_href="&curUrl[href]="+value;
-                       }
-                       function browse_links_setAdditionalValue(name, value) {
-                               additionalValues[name] = value;
-                       }
-               ';
-        // Link setting functions
-        $JScode .= '
-                       function link_typo3Page(id,anchor) {
-                               var parameters = (document.ltargetform.query_parameters && document.ltargetform.query_parameters.value) ? (document.ltargetform.query_parameters.value.charAt(0) == "&" ? "" : "&") + document.ltargetform.query_parameters.value : "";
-                               var theLink = \'' . $this->siteURL . '?id=\' + id + parameters + (anchor ? anchor : "");
-                               browse_links_setAdditionalValue("data-htmlarea-external", "");
-                               plugin.createLink(theLink,cur_target,cur_class,cur_title,additionalValues);
-                               return false;
-                       }
-               ';
-
-        return $JScode;
-    }
-
-    /******************************************************************
-     *
-     * Main functions
-     *
-     ******************************************************************/
-    /**
-     * Rich Text Editor (RTE) link selector (MAIN function)
-     * Generates the link selector for the Rich Text Editor.
-     * Can also be used to select links for the TCEforms (see $wiz)
-     *
-     * @param bool $wiz If set, the "remove link" is not shown in the menu: Used for the "Select link" wizard which is used by the TCEforms
-     * @return string Modified content variable.
-     */
-    protected function main_rte($wiz = false)
-    {
-        // Starting content:
-        $content = $this->doc->startPage($this->getLanguageService()->getLL('Insert/Modify Link', true));
-        // Making menu in top:
-        $content .= $this->doc->getTabMenuRaw($this->buildMenuArray($wiz, $this->getAllowedItems('page,file,folder,url,mail')));
-        // Adding the menu and header to the top of page:
-        $content .= $this->printCurrentUrl($this->curUrlInfo['info']) . '<br />';
-        // Depending on the current action we will create the actual module content for selecting a link:
-        switch ($this->act) {
-            case 'mail':
-                $extUrl = $this->getEmailSelectorHtml();
-                $content .= $this->addAttributesForm($extUrl);
-                break;
-            case 'url':
-                $extUrl = $this->getExternalUrlSelectorHtml();
-                $content .= $this->addAttributesForm($extUrl);
-                break;
-            case 'file':
-            case 'folder':
-                $content .= $this->addAttributesForm();
-                $content .= $this->getFileSelectorHtml(FolderTree::class);
-                break;
-            case 'page':
-                $content .= $this->addAttributesForm();
-                $content .= $this->getPageSelectorHtml(PageTree::class);
-                break;
-            default:
-                // call hook
-                foreach ($this->hookObjects as $hookObject) {
-                    $content .= $hookObject->getTab($this->act);
-                }
-        }
-        // End page, return content:
-        $content .= $this->doc->endPage();
-        $content = $this->doc->insertStylesAndJS($content);
-        return $content;
-    }
-
-    /**
-     * Returns HTML of the email link from
-     *
-     * @return string
-     */
-    protected function getEmailSelectorHtml()
-    {
-        $extUrl = '
-                       <!--
-                               Enter mail address:
-                       -->
-                       <tr>
-                               <td>
-                                       <label>
-                                               ' . $this->getLanguageService()->getLL('emailAddress', true) . ':
-                                       </label>
-                               </td>
-                               <td>
-                                       <input type="text" name="lemail"' . $this->doc->formWidth(20)
-                        . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] == 'mail' ? $this->curUrlInfo['info'] : '')) . '" />
-                                       <input class="btn btn-default" type="submit" value="' . $this->getLanguageService()->getLL('setLink', true)
-                        . '" onclick="browse_links_setTarget(\'\');browse_links_setHref(\'mailto:\'+document.ltargetform.lemail.value);'
-                        . 'browse_links_setAdditionalValue(\'data-htmlarea-external\', \'\');return link_current();" />
-                               </td>
-                       </tr>';
-        return $extUrl;
-    }
-
-    /**
-     * Returns HTML of the external url link from
-     *
-     * @return string
-     */
-    protected function getExternalUrlSelectorHtml()
-    {
-        $extUrl = '
-                       <!--
-                               Enter External URL:
-                       -->
-                       <tr>
-                               <td>
-                                       <label>
-                                               URL:
-                                       </label>
-                               </td>
-                               <td colspan="3">
-                                       <input type="text" name="lurl"' . $this->doc->formWidth(20)
-                        . ' value="' . htmlspecialchars(($this->curUrlInfo['act'] == 'url' ? $this->curUrlInfo['info'] : 'http://'))
-                        . '" />
-                                       <input class="btn btn-default" type="submit" value="' . $this->getLanguageService()->getLL('setLink', true)
-                        . '" onclick="if (/^[A-Za-z0-9_+]{1,8}:/.test(document.ltargetform.lurl.value)) { '
-                        . ' browse_links_setHref(document.ltargetform.lurl.value); } else { browse_links_setHref(\'http://\''
-                        . '+document.ltargetform.lurl.value); } browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\');'
-                        . 'return link_current();" />
-                               </td>
-                       </tr>';
-        return $extUrl;
-    }
-
-    /**
-     * Creates a form for link attributes
-     *
-     * @param string $rows: html code for some initial rows of the table to be wrapped in form
-     * @return string The HTML code of the form
-     */
-    public function addAttributesForm($rows = '')
-    {
-        // additional fields for links
-        $additionalAttributeFields = '';
-        if (
-            isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addAttributeFields'])
-            && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addAttributeFields'])
-        ) {
-            $conf = array();
-            $_params = array(
-                'conf' => &$conf
-            );
-            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][$this->hookName]['addAttributeFields'] as $objRef) {
-                $processor =& GeneralUtility::getUserObj($objRef);
-                $additionalAttributeFields .= $processor->getAttributefields($_params, $this);
-            }
-        }
-
-        // Add page id, target, class selector box, title and parameters fields:
-        $lpageId = $this->addPageIdSelector();
-
-
-        $ltargetForm = '';
-        if ($rows || $lpageId || $queryParameters || $lclass || $ltitle || $ltarget || $rel) {
-            $ltargetForm = '
-                       <!--
-                               Selecting target for link:
-                       -->
-                       <form action="" name="ltargetform" id="ltargetform">
-                               <table id="typo3-linkTarget" class="htmlarea-window-table">' . $rows . $lpageId . $queryParameters . $lclass . $ltitle . $ltarget . $rel . $additionalAttributeFields;
-            if ($this->act === $this->curUrlInfo['act'] && $this->act != 'mail' && $this->curUrlArray['href']) {
-                $ltargetForm .= '
-                                       <tr>
-                                               <td>
-                                               </td>
-                                               <td colspan="3">
-                                                       <input class="btn btn-default" type="submit" value="' . $this->getLanguageService()->getLL('update', true) . '" onclick="'
-                    . ($this->act === 'url' ? 'browse_links_setAdditionalValue(\'data-htmlarea-external\', \'1\'); ' : '')
-                    . 'return link_current();" />
-                                               </td>
-                                       </tr>';
-            }
-            $ltargetForm .= '
-                               </table>
-                       </form>';
-        }
-        return $ltargetForm;
-    }
-
-
-    /**
-     * Add page id selector
-     *
-     * @return string
-     */
-    public function addPageIdSelector()
-    {
-        if ($this->act === 'page' && isset($this->buttonConfig['pageIdSelector.']['enabled'])
-            && $this->buttonConfig['pageIdSelector.']['enabled']
-        ) {
-            return '
-                               <tr>
-                                       <td>
-                                               <label>
-                                                       ' . $this->getLanguageService()->getLL('page_id', true) . ':
-                                               </label>
-                                       </td>
-                                       <td colspan="3">
-                                               <input type="text" size="6" name="luid" /> <input class="btn btn-default" type="submit" value="'
-                            . $this->getLanguageService()->getLL('setLink', true) . '" onclick="return link_typo3Page(document.ltargetform.luid.value);" />
-                                       </td>
-                               </tr>';
-        }
-        return '';
-    }
-
-    /**
-     * Localize a label obtained from Page TSConfig
-     *
-     * @param string $string The label to be localized
-     * @param bool $JScharCode If needs to be converted to an array of char numbers
-     * @return string Localized string
-     */
-    public function getPageConfigLabel($string, $JScharCode = true)
-    {
-        if (substr($string, 0, 4) !== 'LLL:') {
-            $label = $string;
-        } else {
-            $label = $this->getLanguageService()->sL(trim($string));
-        }
-        $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
-        return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
-    }
-
-    /**
-     * @return LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * @return BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-}
index ee325e5..320eb88 100644 (file)
@@ -19,13 +19,12 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Lang\LanguageService;
-use TYPO3\CMS\Recordlist\Controller\LinkBrowserController;
-use TYPO3\CMS\Rtehtmlarea\LinkHandler\RemoveLinkHandler;
+use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
 
 /**
  * Extended controller for link browser
  */
-class BrowseLinksController extends LinkBrowserController
+class BrowseLinksController extends AbstractLinkBrowserController
 {
     /**
      * Active with TYPO3 Element Browser: Contains the name of the form field for which this window
@@ -92,6 +91,46 @@ class BrowseLinksController extends LinkBrowserController
     protected $RTEtsConfigParams;
 
     /**
+     * @var array
+     */
+    protected $classesAnchorDefault = array();
+
+    /**
+     * @var array
+     */
+    protected $classesAnchorDefaultTitle = array();
+
+    /**
+     * @var array
+     */
+    protected $classesAnchorClassTitle = array();
+
+    /**
+     * @var array
+     */
+    protected $classesAnchorDefaultTarget = array();
+
+    /**
+     * @var array
+     */
+    protected $classesAnchorJSOptions = array();
+
+    /**
+     * @var string
+     */
+    protected $defaultLinkTarget = '';
+
+    /**
+     * @var array
+     */
+    protected $additionalAttributes = array();
+
+    /**
+     * @var string
+     */
+    protected $siteUrl = '';
+
+    /**
      * Initialize controller
      */
     protected function init()
@@ -112,8 +151,18 @@ class BrowseLinksController extends LinkBrowserController
     {
         parent::initVariables($request);
 
-        $parameters = $request->getQueryParams();
-        $this->bparams = isset($parameters['bparams']) ? $parameters['bparams'] : '';
+        $queryParameters = $request->getQueryParams();
+        $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
+
+        $this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
+
+        $currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
+        if (isset($currentLinkParts['all'])) {
+            $currentLinkParts = GeneralUtility::get_tag_attributes($queryParameters['curUrl']['all']);
+            $currentLinkParts['url'] = htmlspecialchars_decode($currentLinkParts['href']);
+            unset($currentLinkParts['href']);
+        }
+        $this->currentLinkParts = $currentLinkParts;
 
         // Process bparams
         $pArr = explode('|', $this->bparams);
@@ -147,11 +196,167 @@ class BrowseLinksController extends LinkBrowserController
      */
     protected function initDocumentTemplate()
     {
+        parent::initDocumentTemplate();
+
         $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
         $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rtehtmlarea/RteLinkBrowser');
     }
 
     /**
+     * Initialize $this->currentLink and $this->currentLinkHandler
+     *
+     * @return void
+     */
+    protected function initCurrentUrl()
+    {
+        if (empty($this->currentLinkParts)) {
+            return;
+        }
+
+        if (empty($this->currentLinkParts['data-htmlarea-external'])) {
+            // strip siteUrl prefix except for external and mail links
+            if (strpos($this->currentLinkParts['url'], 'mailto:') === false) {
+                $paramsPosition = strpos($this->currentLinkParts['url'], '?');
+                if ($paramsPosition !== false) {
+                    $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $paramsPosition + 1);
+                }
+            }
+            // special treatment for page links, remove the id= part
+            $idPosition = strpos($this->currentLinkParts['url'], 'id=');
+            if ($idPosition !== false) {
+                $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], $idPosition + 3);
+            }
+
+            // in RTE the additional params are encoded directly at the end of the href part
+            // we need to split this again into dedicated fields
+            $additionalParamsPosition = strpos($this->currentLinkParts['url'], '?');
+            if ($additionalParamsPosition === false) {
+                $additionalParamsPosition = strpos($this->currentLinkParts['url'], '&');
+            }
+            if ($additionalParamsPosition !== false) {
+                $this->currentLinkParts['params'] = substr($this->currentLinkParts['url'], $additionalParamsPosition);
+                $this->currentLinkParts['url'] = substr($this->currentLinkParts['url'], 0, $additionalParamsPosition);
+                // in case the first sign was an ? override it with &
+                $this->currentLinkParts['params'][0] = '&';
+            }
+        }
+
+        parent::initCurrentUrl();
+    }
+
+    /**
+     * Renders the link attributes for the selected link handler
+     *
+     * @return string
+     */
+    public function renderLinkAttributeFields()
+    {
+        // Processing the classes configuration
+        if (!empty($this->buttonConfig['properties.']['class.']['allowedClasses'])) {
+            $classesAnchorArray = GeneralUtility::trimExplode(',', $this->buttonConfig['properties.']['class.']['allowedClasses'], true);
+            // Collecting allowed classes and configured default values
+            $classesAnchor = [
+                'all' => []
+            ];
+            $titleReadOnly = $this->buttonConfig['properties.']['title.']['readOnly']
+                || $this->buttonConfig[$this->currentLinkHandlerId . '.']['properties.']['title.']['readOnly'];
+            if (is_array($this->RTEProperties['classesAnchor.'])) {
+                foreach ($this->RTEProperties['classesAnchor.'] as $label => $conf) {
+                    if (in_array($conf['class'], $classesAnchorArray)) {
+                        $classesAnchor['all'][] = $conf['class'];
+                        if ($conf['type'] === $this->displayedLinkHandlerId) {
+                            $classesAnchor[$conf['type']][] = $conf['class'];
+                            if ($this->buttonConfig[$conf['type'] . '.']['properties.']['class.']['default'] == $conf['class']) {
+                                $this->classesAnchorDefault[$conf['type']] = $conf['class'];
+                                if ($conf['titleText']) {
+                                    $this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText']));
+                                }
+                                if (isset($conf['target'])) {
+                                    $this->classesAnchorDefaultTarget[$conf['type']] = trim($conf['target']);
+                                }
+                            }
+                        }
+                        if ($titleReadOnly && $conf['titleText']) {
+                            $this->classesAnchorClassTitle[$conf['class']] = ($this->classesAnchorDefaultTitle[$conf['type']] = $this->contentLanguageService->sL(trim($conf['titleText'])));
+                        }
+                    }
+                }
+            }
+            // Constructing the class selector options
+            foreach ($classesAnchorArray as $class) {
+                if (!in_array($class, $classesAnchor['all']) || in_array($class, $classesAnchor['all']) && is_array($classesAnchor[$this->displayedLinkHandlerId]) && in_array($class, $classesAnchor[$this->displayedLinkHandlerId])) {
+                    $selected = '';
+                    if ($this->linkAttributeValues['class'] === $class || !$this->linkAttributeValues['class'] && $this->classesAnchorDefault[$this->displayedLinkHandlerId] == $class) {
+                        $selected = 'selected="selected"';
+                    }
+                    $classLabel = !empty($this->RTEProperties['classes.'][$class . '.']['name'])
+                        ? $this->getPageConfigLabel($this->RTEProperties['classes.'][$class . '.']['name'], 0)
+                        : $class;
+                    $classStyle = !empty($this->RTEProperties['classes.'][$class . '.']['value'])
+                        ? $this->RTEProperties['classes.'][$class . '.']['value']
+                        : '';
+                    $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] .= '<option ' . $selected . ' value="' . $class . '"' . ($classStyle ? ' style="' . $classStyle . '"' : '') . '>' . $classLabel . '</option>';
+                }
+            }
+            if ($this->classesAnchorJSOptions[$this->displayedLinkHandlerId] && !($this->buttonConfig['properties.']['class.']['required'] || $this->buttonConfig[$this->currentLinkHandlerId . '.']['properties.']['class.']['required'])) {
+                $selected = '';
+                if (!$this->linkAttributeValues['class'] && !$this->classesAnchorDefault[$this->displayedLinkHandlerId]) {
+                    $selected = 'selected="selected"';
+                }
+                $this->classesAnchorJSOptions[$this->displayedLinkHandlerId] = '<option ' . $selected . ' value=""></option>' . $this->classesAnchorJSOptions[$this->displayedLinkHandlerId];
+            }
+        }
+        // Default target
+        $this->defaultLinkTarget = $this->classesAnchorDefault[$this->currentLinkHandlerId] && $this->classesAnchorDefaultTarget[$this->currentLinkHandlerId]
+            ? $this->classesAnchorDefaultTarget[$this->currentLinkHandlerId]
+            : (isset($this->buttonConfig[$this->currentLinkHandlerId . '.']['properties.']['target.']['default'])
+                ? $this->buttonConfig[$this->currentLinkHandlerId . '.']['properties.']['target.']['default']
+                : (isset($this->buttonConfig['properties.']['target.']['default'])
+                    ? $this->buttonConfig['properties.']['target.']['default']
+                    : ''));
+        // Initializing additional attributes
+        if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes']) {
+            $addAttributes = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins']['TYPO3Link']['additionalAttributes'], true);
+            foreach ($addAttributes as $attribute) {
+                $this->additionalAttributes[$attribute] = isset($this->linkAttributeValues[$attribute]) ? $this->linkAttributeValues[$attribute] : '';
+            }
+        }
+        return parent::renderLinkAttributeFields();
+    }
+
+    /**
+     * Localize a label obtained from Page TSConfig
+     *
+     * @param string $string The label to be localized
+     * @param bool $JScharCode If needs to be converted to an array of char numbers
+     * @return string Localized string
+     */
+    public function getPageConfigLabel($string, $JScharCode = true)
+    {
+        if (substr($string, 0, 4) !== 'LLL:') {
+            $label = $string;
+        } else {
+            $label = $this->getLanguageService()->sL(trim($string));
+        }
+        $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
+        return $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
+    }
+
+    /**
+     * @return string
+     */
+    protected function renderCurrentUrl()
+    {
+        $removeLink = '<a href="#" class="btn btn-default t3js-removeCurrentLink">' . $this->getLanguageService()->getLL('removeLink', true) . '</a>';
+        return '
+            <table border="0" cellpadding="0" cellspacing="0" id="typo3-curUrl">
+                <tr>
+                    <td>' . $this->getLanguageService()->getLL('currentLink', true) . ': ' . htmlspecialchars($this->currentLinkHandler->formatCurrentUrl()) . $removeLink . '</td>
+                </tr>
+            </table>';
+    }
+
+    /**
      * Get the allowed items or tabs
      *
      * @return string[]
@@ -160,14 +365,6 @@ class BrowseLinksController extends LinkBrowserController
     {
         $allowedItems = parent::getAllowedItems();
 
-        // do not show the "removeLink" item if there is no current link
-        if (!$this->currentLink) {
-            $position = array_search('removeLink', $allowedItems, true);
-            if ($position !== false) {
-                unset($allowedItems[$position]);
-            }
-        }
-
         $blindLinkOptions = isset($this->RTEProperties['default.']['blindLinkOptions'])
             ? GeneralUtility::trimExplode(',', $this->RTEProperties['default.']['blindLinkOptions'], true)
             : [];
@@ -208,53 +405,41 @@ class BrowseLinksController extends LinkBrowserController
         $fieldRenderingDefinitions['title'] = $this->getTitleField();
         $fieldRenderingDefinitions['class'] = $this->getClassField();
         $fieldRenderingDefinitions['target'] = $this->getTargetField();
-        $fieldRenderingDefinitions['params'] = $this->getParamsField();
         $fieldRenderingDefinitions['rel'] = $this->getRelField();
-    }
-
-
-    /**
-     * Add rel field
-     *
-     * @return string
-     */
-    protected function getRelField()
-    {
-        // Unset rel attribute if we changed tab
-        $currentRel = $this->curUrlInfo['act'] === $this->act && isset($this->curUrlArray['rel']) ? $this->curUrlArray['rel'] : '';
-        if (($this->act === 'page' || $this->act === 'url' || $this->act === 'file')
-            && isset($this->buttonConfig['relAttribute.']['enabled']) && $this->buttonConfig['relAttribute.']['enabled']
+        if (
+            isset($this->buttonConfig['queryParametersSelector.']['enabled'])
+            && !$this->buttonConfig['queryParametersSelector.']['enabled']
         ) {
-            return '
-                                               <tr>
-                                                       <td><label>' . $this->getLanguageService()->getLL('linkRelationship', true) . ':</label></td>
-                                                       <td colspan="3">
-                                                               <input type="text" name="lrel" value="' . $currentRel . '"  '
-            . $this->doc->formWidth(30) . ' />
-                                                       </td>
-                                               </tr>';
+            unset($fieldRenderingDefinitions['params']);
         }
-        return '';
+        return $fieldRenderingDefinitions;
     }
 
-
     /**
-     * Add query parameter selector
+     * Add rel field
      *
      * @return string
      */
-    protected function getParamsField()
+    protected function getRelField()
     {
-        if (empty($this->buttonConfig['queryParametersSelector.']['enabled'])) {
+        if (empty($this->buttonConfig['relAttribute.']['enabled'])) {
             return '';
         }
+        // @todo add rel to attributes
+        $currentRel = $this->displayedLinkHandler === $this->currentLinkHandler && !empty($this->currentLinkParts)
+            ? $this->linkAttributeValues['rel']
+            : '';
+        // @todo define label "linkRelationship" below in xlf
         return '
-                       <tr>
-                               <td><label>' . $this->getLanguageService()->getLL('query_parameters', true) . ':</label></td>
-                               <td colspan="3">
-                                       <input type="text" name="query_parameters" value="' . ($this->curUrlInfo['query'] ?: '') . '" ' . $this->doc->formWidth(30) . ' />
-                               </td>
-                       </tr>';
+                               <form action="" name="lrelform" id="lrelform">
+                                       <table border="0" cellpadding="2" cellspacing="1" id="typo3-linkRel">
+                                               <tr>
+                                                       <td><label>' . $this->getLanguageService()->getLL('linkRelationship', true) . ':</label></td>
+                                                       <td colspan="3"><input type="text" name="lrel" value="' . $currentRel . '" /></td>
+                                               </tr>
+                                       </table>
+                               </form>
+                       ';
     }
 
     /**
@@ -268,31 +453,34 @@ class BrowseLinksController extends LinkBrowserController
         if (is_array($this->buttonConfig['targetSelector.'])) {
             $targetSelectorConfig = $this->buttonConfig['targetSelector.'];
         }
-        // Reset the target to default if we changed tab
-        $currentTarget = $this->curUrlInfo['act'] === $this->act && isset($this->curUrlArray['target']) ? $this->curUrlArray['target'] : '';
-        $target = $currentTarget ?: $this->defaultLinkTarget;
+        $target = $this->linkAttributeValues['target'] ?: $this->defaultLinkTarget;
         $lang = $this->getLanguageService();
-        $ltarget = '
-                               <tr id="ltargetrow"' . ($targetSelectorConfig['disabled'] ? ' style="display: none;"' : '') . '>
-                                       <td><label>' . $lang->getLL('target', true) . ':</label></td>
-                                       <td><input type="text" name="ltarget" onchange="browse_links_setTarget(this.value);" value="'
-            . htmlspecialchars($target) . '"' . $this->doc->formWidth(10) . ' /></td>';
-        $ltarget .= '
-                                       <td colspan="2">';
+        $targetSelector = '';
+
         if (!$targetSelectorConfig['disabled']) {
-            $ltarget .= '
-                                               <select name="ltarget_type" onchange="browse_links_setTarget(this.options[this.selectedIndex].value);document.ltargetform.ltarget.value=this.options[this.selectedIndex].value;this.selectedIndex=0;">
-                                                       <option></option>
+            $targetSelector = '
+                                               <select name="ltarget_type" class="t3js-targetPreselect">
+                                              &nbs