[!!!][TASK] Fluidification of Clipboard 67/46367/24
authorJan Helke <typo3@helke.de>
Fri, 29 Jan 2016 17:32:38 +0000 (18:32 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 3 Dec 2016 10:17:26 +0000 (11:17 +0100)
Moves most of the HTML from the PHP to an own Template.
In fact in line 408 and in the function linkItemText are some remaining
html tags, but removing those would require some major refactoring.

Resolves: #73016
Releases: master
Change-Id: Ie9859758885be0516ff8aeb58c473c5634848c81
Reviewed-on: https://review.typo3.org/46367
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Florian Mast <flo.mast@web.de>
Reviewed-by: Markus Sommer <markussom@posteo.de>
Tested-by: Markus Sommer <markussom@posteo.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/backend/Classes/Clipboard/Clipboard.php
typo3/sysext/backend/Resources/Private/Partials/Clipboard/CopymodeSelector.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Partials/Clipboard/MenuSelector.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Partials/Clipboard/Tab.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Partials/Clipboard/TabContent.html [new file with mode: 0644]
typo3/sysext/backend/Resources/Private/Templates/Clipboard/Main.html [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Breaking-73016-RenamingOfClipboard-printContentFromTabToGetContentFromTab.rst [new file with mode: 0644]

index 9409310..94afd2b 100644 (file)
@@ -19,12 +19,13 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
-use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
 use TYPO3\CMS\Core\Resource\ResourceFactory;
 use TYPO3\CMS\Core\Type\Bitmask\JsConfirmation;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
  * TYPO3 clipboard for records and files
@@ -87,11 +88,20 @@ class Clipboard
     protected $iconFactory;
 
     /**
+     * @var StandaloneView
+     */
+    protected $view;
+
+    /**
      * Construct
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     * @throws \InvalidArgumentException
      */
     public function __construct()
     {
         $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+        $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+        $this->view = $this->getStandaloneView();
     }
 
     /*****************************************
@@ -248,45 +258,43 @@ class Clipboard
      * Prints the clipboard
      *
      * @return string HTML output
+     * @throws \BadFunctionCallException
      */
     public function printClipboard()
     {
         $languageService = $this->getLanguageService();
-        $out = [];
         $elementCount = count($this->elFromTable($this->fileMode ? '_FILE' : ''));
         // Copymode Selector menu
         $copymodeUrl = GeneralUtility::linkThisScript();
-        $moveLabel = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:moveElements'));
-        $copyLabel = htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:copyElements'));
 
-        $copymodeSelector = '
-                       <div class="btn-group">
-                               <button class="btn btn-default dropdown-toggle" type="button" id="copymodeSelector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
-                                       ' . ($this->currentMode() === 'copy' ? $copyLabel : $moveLabel) . '
-                                       <span class="caret"></span>
-                               </button>
-                               <ul class="dropdown-menu" aria-labelledby="copymodeSelector">
-                                       <li><a href="#" onclick="document.getElementById(\'clipboard_form\').method=\'POST\'; document.getElementById(\'clipboard_form\').action=' . htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=')) . '; document.getElementById(\'clipboard_form\').submit(); return true;">' . $moveLabel . '</a></li>
-                                       <li><a href="#" onclick="document.getElementById(\'clipboard_form\').method=\'POST\'; document.getElementById(\'clipboard_form\').action=' . htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=1')) . '; document.getElementById(\'clipboard_form\').submit(); return true;">' . $copyLabel . '</a></li>
-                               </ul>
-                       </div>
-                       ';
+        $this->view->assign('actionCopyModeUrl', htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=')));
+        $this->view->assign('actionCopyModeUrl1', htmlspecialchars(GeneralUtility::quoteJSvalue($copymodeUrl . '&CB[setCopyMode]=1')));
+        $this->view->assign('currentMode', $this->currentMode());
+        $this->view->assign('elementCount', $elementCount);
 
-        $deleteLink = '';
-        $menuSelector = '';
         if ($elementCount) {
             $removeAllUrl = GeneralUtility::linkThisScript(['CB' => ['removeAll' => $this->current]]);
+            $this->view->assign('removeAllUrl', $removeAllUrl);
 
             // Selector menu + clear button
             $optionArray = [];
             // Import / Export link:
             if (ExtensionManagementUtility::isLoaded('impexp')) {
                 $url = BackendUtility::getModuleUrl('xMOD_tximpexp', $this->exportClipElementParameters());
-                $optionArray[] = '<li><a href="' . htmlspecialchars($url) . '">' . $this->clLabel('export', 'rm') . '</a></li>';
+                $optionArray[] = [
+                    'label' => $this->clLabel('export', 'rm'),
+                    'uri' => $url
+                ];
             }
             // Edit:
             if (!$this->fileMode) {
-                $optionArray[] = '<li><a href="#" onclick="' . htmlspecialchars(('window.location.href=' . GeneralUtility::quoteJSvalue($this->editUrl() . '&returnUrl=') . '+top.rawurlencode(window.location.href);')) . '">' . $this->clLabel('edit', 'rm') . '</a></li>';
+                $optionArray[] = [
+                    'label' => $this->clLabel('edit', 'rm'),
+                    'uri' => '#',
+                    'additionalAttributes' => [
+                        'onclick' => htmlspecialchars('window.location.href=' . GeneralUtility::quoteJSvalue($this->editUrl() . '&returnUrl=') . '+top.rawurlencode(window.location.href);'),
+                    ]
+                ];
             }
 
             // Delete referenced elements:
@@ -294,6 +302,7 @@ class Clipboard
             if ($this->getBackendUser()->jsConfirmation(JsConfirmation::DELETE)) {
                 $confirmationCheck = true;
             }
+
             $confirmationMessage = sprintf(
                 $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.deleteClip'),
                 $elementCount
@@ -305,89 +314,60 @@ class Clipboard
                 ->sL('LLL:EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf:buttons.confirm.delete_elements.yes');
             $btnCancelText = $languageService
                 ->sL('LLL:EXT:lang/Resources/Private/Language/locallang_alt_doc.xlf:buttons.confirm.delete_elements.no');
-            $optionArray[] = '<li><a'
-                . (($confirmationCheck) ? ' class="t3js-modal-trigger"' : '')
-                . ' href="' . htmlspecialchars($returnUrl) . '"'
-                . ' data-severity="warning"'
-                . ' data-button-close-text="' . htmlspecialchars($btnCancelText) . '"'
-                . ' data-button-ok-text="' . htmlspecialchars($btnOkText) . '"'
-                . ' data-content="' . htmlspecialchars($confirmationMessage) . '"'
-                . ' data-title="' . htmlspecialchars($title) . '">'
-                . htmlspecialchars($title) . '</a></li>';
+            $optionArray[] = [
+                'label' => htmlspecialchars($title),
+                'uri' => $returnUrl,
+                'additionalAttributes' => [
+                    'class' => $confirmationCheck ? 't3js-modal-trigger' : '',
+                ],
+                'data' => [
+                    'severity' => 'warning',
+                    'button-close-text' => htmlspecialchars($btnCancelText),
+                    'button-ok-text' => htmlspecialchars($btnOkText),
+                    'content' => htmlspecialchars($confirmationMessage),
+                    'title' => htmlspecialchars($title)
+                ]
+            ];
 
             // Clear clipboard
-            $optionArray[] = '<li><a href="' . htmlspecialchars($removeAllUrl) . '#clip_head">' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.clipboard.clear_clipboard')) . '</a></li>';
-            $deleteLink = '<a class="btn btn-danger" href="' . htmlspecialchars($removeAllUrl) . '#clip_head" title="' . htmlspecialchars($languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.clear')) . '">' . $this->iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL)->render(SvgIconProvider::MARKUP_IDENTIFIER_INLINE) . '</a>';
-
-            // menuSelector
-            $menuSelector = '
-                       <div class="btn-group">
-                               <button class="btn btn-default dropdown-toggle" type="button" id="menuSelector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
-                                       ' . $this->clLabel('menu', 'rm') . '
-                                       <span class="caret"></span>
-                               </button>
-                               <ul class="dropdown-menu" aria-labelledby="menuSelector">
-                                       ' . implode('', $optionArray) . '
-                               </ul>
-                       </div>
-                       ';
+            $optionArray[] = [
+                'label' => $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.clipboard.clear_clipboard', true),
+                'uri' => $removeAllUrl . '#clip_head'
+            ];
+            $this->view->assign('optionArray', $optionArray);
         }
 
-        $out[] = '
-                       <tr>
-                               <td colspan="2" nowrap="nowrap" width="95%">' . $copymodeSelector . ' ' . $menuSelector . '</td>
-                               <td nowrap="nowrap" class="col-control">' . $deleteLink . '</td>
-                       </tr>';
-
         // Print header and content for the NORMAL tab:
-        // check for current item so it can be wrapped in strong tag
-        $current = ($this->current == 'normal');
-        $out[] = '
-                       <tr>
-                               <td colspan="3"><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(['CB' => ['setP' => 'normal']])) . '#clip_head" title="' . $this->clLabel('normal-description') . '">'
-                    . '<span class="t3-icon fa ' . ($current ? 'fa-check-circle' : 'fa-circle-o') . '"></span>'
-                    . $this->padTitleWrap($this->clLabel('normal'), 'normal', $current)
-                    . '</a></td>
-                       </tr>';
+        $this->view->assign('current', $this->current);
+        $tabArray = [];
+        $tabArray['normal'] = [
+            'id' => 'normal',
+            'number' => 0,
+            'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'normal']]),
+            'description' => 'normal-description',
+            'label' => 'labels.normal',
+            'padding' => $this->padTitle('normal')
+        ];
         if ($this->current == 'normal') {
-            $out = array_merge($out, $this->printContentFromTab('normal'));
+            $tabArray['normal']['content'] = $this->getContentFromTab('normal');
         }
         // Print header and content for the NUMERIC tabs:
         for ($a = 1; $a <= $this->numberTabs; $a++) {
-            // check for current item so it can be wrapped in strong tag
-            $current = ($this->current == 'tab_' . $a);
-            $out[] = '
-                               <tr>
-                                       <td colspan="3"><a href="' . htmlspecialchars(GeneralUtility::linkThisScript(['CB' => ['setP' => ('tab_' . $a)]])) . '#clip_head" title="' . $this->clLabel('cliptabs-description') . '">'
-                        . '<span class="t3-icon fa ' . ($current ? 'fa-check-circle' : 'fa-circle-o') . '"></span>'
-                        . $this->padTitleWrap(sprintf($this->clLabel('cliptabs-name'), $a), ('tab_' . $a), $current)
-                        . '</a></td>
-                               </tr>';
-            if ($this->current == 'tab_' . $a) {
-                $out = array_merge($out, $this->printContentFromTab('tab_' . $a));
+            $tabArray['tab_' . $a] = [
+                'id' => 'tab_' . $a,
+                'number' => $a,
+                'url' => GeneralUtility::linkThisScript(['CB' => ['setP' => 'tab_' . $a]]),
+                'description' => 'cliptabs-description',
+                'label' => 'labels.cliptabs-name',
+                'padding' => $this->padTitle('tab_' . $a)
+            ];
+            if ($this->current === 'tab_' . $a) {
+                $tabArray['tab_' . $a]['content'] = $this->getContentFromTab('tab_' . $a);
             }
         }
-        // Wrap accumulated rows in a table:
-        $output = '<a name="clip_head"></a>
-
-                       <!--
-                               TYPO3 Clipboard:
-                       -->
-                       <div class="row">
-                               <div class="col-sm-12">
-                                       <div class="panel panel-default">
-                                               <div class="panel-heading">' . BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons')) . '</div>
-                                               <table class="table">
-                                                       ' . implode('', $out) . '
-                                               </table>
-                                       </div>
-                               </div>
-                       </div>
-               ';
-        // Wrap in form tag:
-        $output = '<form action="" id="clipboard_form">' . $output . '</form>';
-        // Return the accumulated content:
-        return $output;
+        $this->view->assign('clipboardHeader', BackendUtility::wrapInHelp('xMOD_csh_corebe', 'list_clipboard', $this->clLabel('clipboard', 'buttons')));
+        $this->view->assign('tabArray', $tabArray);
+        return $this->view->render();
     }
 
     /**
@@ -397,7 +377,7 @@ class Clipboard
      * @param string $pad Pad reference
      * @return array Array with table rows for the clipboard.
      */
-    public function printContentFromTab($pad)
+    public function getContentFromTab($pad)
     {
         $lines = [];
         if (is_array($this->clipData[$pad]['el'])) {
@@ -405,33 +385,29 @@ class Clipboard
                 if ($v) {
                     list($table, $uid) = explode('|', $k);
                     // Rendering files/directories on the clipboard
-                    if ($table == '_FILE') {
+                    if ($table === '_FILE') {
                         $fileObject = ResourceFactory::getInstance()->retrieveFileOrFolderObject($v);
                         if ($fileObject) {
-                            $thumb = '';
+                            $thumb = [];
                             $folder = $fileObject instanceof \TYPO3\CMS\Core\Resource\Folder;
                             $size = $folder ? '' : '(' . GeneralUtility::formatSize($fileObject->getSize()) . 'bytes)';
-                            $icon = '<span title="' . htmlspecialchars($fileObject->getName() . ' ' . $size) . '">' . $this->iconFactory->getIconForResource($fileObject, Icon::SIZE_SMALL)->render() . '</span>';
-                            if (!$folder && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
-                                $processedFile = $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, []);
-                                if ($processedFile) {
-                                    $thumbUrl = $processedFile->getPublicUrl(true);
-                                    $thumb = '<br /><img src="' . htmlspecialchars($thumbUrl) . '" ' .
-                                            'width="' . $processedFile->getProperty('width') . '" ' .
-                                            'height="' . $processedFile->getProperty('height') . '" ' .
-                                            'title="' . htmlspecialchars($fileObject->getName()) . '" alt="" />';
-                                }
+                            if (!$folder && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
+                                    $fileObject->getExtension())
+                            ) {
+                                $thumb = [
+                                    'image' => $fileObject->process(\TYPO3\CMS\Core\Resource\ProcessedFile::CONTEXT_IMAGEPREVIEW, []),
+                                    'title' => htmlspecialchars($fileObject->getName())
+                                ];
                             }
-                            $lines[] = '
-                                                               <tr>
-                                                                       <td nowrap="nowrap" class="col-icon">' . $icon . '</td>
-                                                                       <td nowrap="nowrap" width="95%">' . $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(), $this->getBackendUser()->uc['titleLen'])), $fileObject->getName()) . ($pad == 'normal' ? ' <strong>(' . ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) . ')</strong>' : '') . '&nbsp;' . $thumb . '</td>
-                                                                       <td nowrap="nowrap" class="col-control">
-                                                                               <div class="btn-group">
-                                                                                       <a class="btn btn-default" href="#" onclick="' . htmlspecialchars(('top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($v) . '); return false;')) . '"title="' . $this->clLabel('info', 'cm') . '">' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . '</a>' . '<a class="btn btn-default" href="' . htmlspecialchars($this->removeUrl('_FILE', GeneralUtility::shortMD5($v))) . '#clip_head" title="' . $this->clLabel('removeItem') . '">' . $this->iconFactory->getIcon('actions-selection-delete', Icon::SIZE_SMALL)->render() . '</a>
-                                                                               </div>
-                                                                       </td>
-                                                               </tr>';
+                            $lines[] = [
+                                'icon' => '<span title="' . htmlspecialchars($fileObject->getName() . ' ' . $size) . '">' . $this->iconFactory->getIconForResource($fileObject,
+                                        Icon::SIZE_SMALL)->render() . '</span>',
+                                'title' => $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs($fileObject->getName(),
+                                    $this->getBackendUser()->uc['titleLen'])), $fileObject->getName()),
+                                'thumb' => $thumb,
+                                'infoLink' => htmlspecialchars('top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', ' . GeneralUtility::quoteJSvalue($v) . '); return false;'),
+                                'removeLink' => $this->removeUrl('_FILE', GeneralUtility::shortMD5($v))
+                            ];
                         } else {
                             // If the file did not exist (or is illegal) then it is removed from the clipboard immediately:
                             unset($this->clipData[$pad]['el'][$k]);
@@ -441,19 +417,18 @@ class Clipboard
                         // Rendering records:
                         $rec = BackendUtility::getRecordWSOL($table, $uid);
                         if (is_array($rec)) {
-                            $lines[] = '
-                                                               <tr>
-                                                                       <td nowrap="nowrap" class="col-icon">' . $this->linkItemText($this->iconFactory->getIconForRecord($table, $rec, Icon::SIZE_SMALL)->render(), $rec, $table) . '</td>
-                                                                       <td nowrap="nowrap" width="95%">' . $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $rec), $this->getBackendUser()->uc['titleLen'])), $rec, $table) . ($pad == 'normal' ? ' <strong>(' . ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) . ')</strong>' : '') . '&nbsp;</td>
-                                                                       <td nowrap="nowrap" class="col-control">
-                                                                               <div class="btn-group">
-                                                                                       <a class="btn btn-default" href="#" onclick="' . htmlspecialchars(('top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', \'' . (int)$uid . '\'); return false;')) . '" title="' . $this->clLabel('info', 'cm') . '">' . $this->iconFactory->getIcon('actions-document-info', Icon::SIZE_SMALL)->render() . '</a>' . '<a class="btn btn-default" href="' . htmlspecialchars($this->removeUrl($table, $uid)) . '#clip_head" title="' . $this->clLabel('removeItem') . '">' . $this->iconFactory->getIcon('actions-selection-delete', Icon::SIZE_SMALL)->render() . '</a>
-                                                                               </div>
-                                                                       </td>
-                                                               </tr>';
-                            $localizationData = $this->getLocalizations($table, $rec, '', $pad);
-                            if ($localizationData) {
-                                $lines[] = $localizationData;
+                            $lines[] = [
+                                'icon' => $this->linkItemText($this->iconFactory->getIconForRecord($table, $rec,
+                                    Icon::SIZE_SMALL)->render(), $rec, $table),
+                                'title' => $this->linkItemText(htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table,
+                                    $rec), $this->getBackendUser()->uc['titleLen'])), $rec, $table),
+                                'infoLink' => htmlspecialchars('top.launchView(' . GeneralUtility::quoteJSvalue($table) . ', \'' . (int)$uid . '\'); return false;'),
+                                'removeLink' => $this->removeUrl($table, $uid)
+                            ];
+
+                            $localizationData = $this->getLocalizations($table, $rec, '', '');
+                            if (!empty($localizationData)) {
+                                $lines = array_merge($lines, $localizationData);
                             }
                         } else {
                             unset($this->clipData[$pad]['el'][$k]);
@@ -527,44 +502,30 @@ class Clipboard
             }
             $rows = $queryBuilder->execute()->fetchAll();
             if (is_array($rows)) {
-                $modeData = '';
-                if ($pad == 'normal') {
-                    $mode = $this->clipData['normal']['mode'] == 'copy' ? 'copy' : 'cut';
-                    $modeData = ' <strong>(' . $this->clLabel($mode, 'cm') . ')</strong>';
-                }
                 foreach ($rows as $rec) {
-                    $lines[] = '
-                                       <tr>
-                                               <td nowrap="nowrap" class="col-icon">' . $this->iconFactory->getIconForRecord($table, $rec, Icon::SIZE_SMALL)->render() . '</td>
-                                               <td nowrap="nowrap" width="95%">' . htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $rec), $this->getBackendUser()->uc['titleLen'])) . $modeData . '</td>
-                                               <td nowrap="nowrap" class="col-control"></td>
-                                       </tr>';
+                    $lines[] = [
+                        'icon' => $this->iconFactory->getIconForRecord($table, $rec, Icon::SIZE_SMALL)->render(),
+                        'title' => htmlspecialchars(GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $rec), $this->getBackendUser()->uc['titleLen']))
+                    ];
                 }
             }
         }
-        return implode('', $lines);
+        return $lines;
     }
 
     /**
-     * Wraps title of pad in bold-tag and maybe the number of elements if any.
-     * Only applies bold-tag if the item is active
+     * Warps title with number of elements if any.
      *
-     * @param string  $str String (already htmlspecialchars()'ed)
      * @param string  $pad Pad reference
-     * @param bool $active is currently active
-     * @return string HTML output (htmlspecialchar'ed content inside of tags.)
+     * @return string padding
      */
-    public function padTitleWrap($str, $pad, $active)
+    public function padTitle($pad)
     {
         $el = count($this->elFromTable($this->fileMode ? '_FILE' : '', $pad));
         if ($el) {
-            $str .=  ' (' . ($pad == 'normal' ? ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) : htmlspecialchars($el)) . ')';
-        }
-        if ($active === true) {
-            return '<strong>' . $str . '</strong>';
-        } else {
-            return '<span class="text-muted">' . $str . '</span>';
+            return ' (' . ($pad == 'normal' ? ($this->clipData['normal']['mode'] == 'copy' ? $this->clLabel('copy', 'cm') : $this->clLabel('cut', 'cm')) : htmlspecialchars($el)) . ')';
         }
+        return '';
     }
 
     /**
@@ -1133,4 +1094,25 @@ class Clipboard
     {
         return $GLOBALS['BE_USER'];
     }
+
+    /**
+     * returns a new standalone view, shorthand function
+     *
+     * @return StandaloneView
+     * @throws \InvalidArgumentException
+     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidExtensionNameException
+     */
+    protected function getStandaloneView()
+    {
+        /** @var StandaloneView $view */
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $view->setLayoutRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Layouts')]);
+        $view->setPartialRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Partials')]);
+        $view->setTemplateRootPaths([GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates')]);
+
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/Templates/Clipboard/Main.html'));
+
+        $view->getRequest()->setControllerExtensionName('Backend');
+        return $view;
+    }
 }
diff --git a/typo3/sysext/backend/Resources/Private/Partials/Clipboard/CopymodeSelector.html b/typo3/sysext/backend/Resources/Private/Partials/Clipboard/CopymodeSelector.html
new file mode 100644 (file)
index 0000000..7f61e09
--- /dev/null
@@ -0,0 +1,17 @@
+<div class="btn-group">
+       <button class="btn btn-default dropdown-toggle" type="button" id="copymodeSelector" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+               <f:if condition="{currentMode} == 'copy'">
+                       <f:then>
+                               {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:copyElements')}
+                       </f:then>
+                       <f:else>
+                               {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:moveElements')}
+                       </f:else>
+               </f:if>
+               <span class="caret"></span>
+       </button>
+       <ul class="dropdown-menu" aria-labelledby="copymodeSelector">
+               <li><a href="#" onclick="document.getElementById('clipboard_form').method='POST'; document.getElementById('clipboard_form').action={actionCopyModeUrl}; document.getElementById('clipboard_form').submit(); return true;">{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:moveElements')}</a></li>
+               <li><a href="#" onclick="document.getElementById('clipboard_form').method='POST'; document.getElementById('clipboard_form').action={actionCopyModeUrl1}; document.getElementById('clipboard_form').submit(); return true;">{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_misc.xlf:copyElements')}</a></li>
+       </ul>
+</div>
diff --git a/typo3/sysext/backend/Resources/Private/Partials/Clipboard/MenuSelector.html b/typo3/sysext/backend/Resources/Private/Partials/Clipboard/MenuSelector.html
new file mode 100644 (file)
index 0000000..b789e2e
--- /dev/null
@@ -0,0 +1,14 @@
+<div class="btn-group">
+       <button class="btn btn-default dropdown-toggle" type="button" id="menuSelector" data-toggle="dropdown"
+                                       aria-haspopup="true" aria-expanded="true">
+               {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.menu')}
+               <span class="caret"></span>
+       </button>
+       <ul class="dropdown-menu" aria-labelledby="menuSelector">
+               <f:for each="{optionArray}" as="option" key="key">
+                       <li>
+                               <f:link.external uri="{option.uri}" data="{option.data}" additionalAttributes="{option.additionalAttributes}" defaultScheme="">{option.label}</f:link.external>
+                       </li>
+               </f:for>
+       </ul>
+</div>
diff --git a/typo3/sysext/backend/Resources/Private/Partials/Clipboard/Tab.html b/typo3/sysext/backend/Resources/Private/Partials/Clipboard/Tab.html
new file mode 100644 (file)
index 0000000..e4a296c
--- /dev/null
@@ -0,0 +1,28 @@
+<tr>
+       <td colspan="3"><a href="{tab.url}#clip_head"
+                                                                                title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:{tab.description}')}">
+               <f:if condition="{current} == {tab.id}">
+                       <f:then>
+                               <span class="t3-icon fa fa-check-circle"></span><strong>
+                               <f:format.printf
+                                       arguments="{1: '{tab.number}'}" value="{f:translate(key:'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:{tab.label}')}">{f:translate(key:'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:{tab.label}')}
+                               </f:format.printf>
+                               {tab.padding}
+                       </strong>
+                       </f:then>
+                       <f:else>
+                               <span class="t3-icon fa fa-circle-o"></span><span class="text-muted"><f:format.printf
+                               arguments="{1: '{tab.number}'}" value="{f:translate(key:'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:{tab.label}')}">{f:translate(key:'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:{tab.label}')}
+                       </f:format.printf>{tab.padding}</span>
+                       </f:else>
+               </f:if>
+       </a></td>
+</tr>
+<f:if condition="{current} == {tab.id}">
+       <f:format.raw>{tab.content_old}</f:format.raw>
+       <f:if condition="{tab.content}">
+               <f:for each="{tab.content}" as="content" key="key">
+                       <f:render partial="Clipboard/TabContent" arguments="{tab: tab, content: content, currentMode: currentMode}"/>
+               </f:for>
+       </f:if>
+</f:if>
diff --git a/typo3/sysext/backend/Resources/Private/Partials/Clipboard/TabContent.html b/typo3/sysext/backend/Resources/Private/Partials/Clipboard/TabContent.html
new file mode 100644 (file)
index 0000000..0b0eb33
--- /dev/null
@@ -0,0 +1,41 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+<tr>
+       <td nowrap="nowrap" class="col-icon">
+               <f:format.raw>{content.icon}</f:format.raw>
+       </td>
+       <td nowrap="nowrap" width="95%">
+               <f:format.raw>{content.title}</f:format.raw>
+               <f:if condition="{tab.id} == 'normal'">
+                       <strong>(
+                               <f:if condition="{currentMode} == 'copy'">
+                                       <f:then>
+                                               {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.copy')}
+                                       </f:then>
+                                       <f:else>
+                                               {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.cut')}
+                                       </f:else>
+                               </f:if>
+                               )</strong>
+               </f:if>
+               <f:if condition="{content.thumb}">
+                       <br>
+                       <f:image image="{content.thumb.image}" title="{content.thumb.title}"/>
+               </f:if>
+       </td>
+       <td nowrap="nowrap" class="col-control">
+               <div class="btn-group">
+                       <f:if condition="{content.infoLink}">
+                               <a class="btn btn-default" href="#" onclick="{content.infoLink}"
+                                        title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.info')}">
+                                       <f:format.raw><core:icon identifier="actions-document-info" alternativeMarkupIdentifier="inline"/></f:format.raw>
+                               </a>
+                       </f:if>
+                       <f:if condition="{content.removeLink}">
+                               <a class="btn btn-default" href="{content.removeLink}#clip_head"
+                                        title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.removeItem')}">
+                                       <f:format.raw><core:icon identifier="actions-selection-delete" alternativeMarkupIdentifier="inline"/></f:format.raw>
+                               </a>
+                       </f:if>
+               </div>
+       </td>
+</tr>
diff --git a/typo3/sysext/backend/Resources/Private/Templates/Clipboard/Main.html b/typo3/sysext/backend/Resources/Private/Templates/Clipboard/Main.html
new file mode 100644 (file)
index 0000000..25e3699
--- /dev/null
@@ -0,0 +1,34 @@
+{namespace core = TYPO3\CMS\Core\ViewHelpers}
+<form action="" id="clipboard_form">
+       <a name="clip_head"></a>
+       <div class="row">
+               <div class="col-sm-12">
+                       <div class="panel panel-default">
+                               <div class="panel-heading">
+                                       <f:format.raw>{clipboardHeader}</f:format.raw>
+                               </div>
+                               <table class="table">
+                                       <tr>
+                                               <td colspan="2" nowrap="nowrap" width="95%">
+                                                       <f:render partial="Clipboard/CopymodeSelector" arguments="{_all}"/>
+                                                       <f:if condition="{elementCount}">
+                                                               <f:render partial="Clipboard/MenuSelector" arguments="{_all}"/>
+                                                       </f:if>
+                                               </td>
+                                               <td nowrap="nowrap" class="col-control">
+                                                       <f:if condition="{elementCount}">
+                                                               <a href="{removeAllUrl}#clip_head"
+                                                                        title="{f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:buttons.clear')}" class="btn btn-danger">
+                                                                       <f:format.raw><core:icon identifier="actions-document-close" alternativeMarkupIdentifier="inline"></core:icon></f:format.raw>
+                                                               </a>
+                                                       </f:if>
+                                               </td>
+                                       </tr>
+                                       <f:for each="{tabArray}" as="tab" key="key">
+                                               <f:render partial="Clipboard/Tab" arguments="{tab: tab, current: current, currentMode: currentMode}"/>
+                                       </f:for>
+                               </table>
+                       </div>
+               </div>
+       </div>
+</form>
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-73016-RenamingOfClipboard-printContentFromTabToGetContentFromTab.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-73016-RenamingOfClipboard-printContentFromTabToGetContentFromTab.rst
new file mode 100644 (file)
index 0000000..964d173
--- /dev/null
@@ -0,0 +1,32 @@
+.. include:: ../../Includes.txt
+
+==================================================================================
+Breaking: #73016 - Renaming of Clipboard->printContentFromTab to getContentFromTab
+==================================================================================
+
+See :issue:`73016`
+
+Description
+===========
+
+During the fluidification of the clipboard, it became obvious that the method name printContentFromTab doesn't describe the function of the method correctly anymore. So it has been renamed into getContentFromTab.
+
+
+Impact
+======
+
+This is a public method, so it could be the case that some unknown extension calls the old function. But as no TER extension or the core itself calls the method, no deprecation was needed.
+
+
+Affected Installations
+======================
+
+Every extension that calls Clipboard->printContentFromTab().
+
+
+Migration
+=========
+
+Change the call from Clipboard->printContentFromTab to Clipboard->getContentFromTab.
+
+.. index:: Backend
\ No newline at end of file