Commit 320c5ed9 authored by Mathias Schreiber's avatar Mathias Schreiber Committed by Andreas Fernandez
Browse files

[BUGFIX] Unify Tooltip in the Backend

All tooltips in the backend now use the same API
and visual appeal.

Resolves: #15030
Releases: master
Change-Id: I56f8d024ac80dd956a2de5087ebd1b69ff1403f9
Reviewed-on: https://review.typo3.org/44359

Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
parent 6fa4d6ba
......@@ -135,10 +135,11 @@ class MoveElementController extends AbstractModule
$lang = $this->getLanguageService();
if ($this->page_id) {
$backendUser = $this->getBackendUser();
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
// Get record for element:
$elRow = BackendUtility::getRecordWSOL($this->table, $this->moveUid);
// Headerline: Icon, record title:
$headerLine = '<span title="' . BackendUtility::getRecordIconAltText($elRow, $this->table) . '">' . $this->moduleTemplate->getIconFactory()->getIconForRecord($this->table, $elRow, Icon::SIZE_SMALL)->render() . '</span>';
$headerLine = '<span ' . BackendUtility::getRecordToolTip($elRow, $this->table) . '>' . $this->moduleTemplate->getIconFactory()->getIconForRecord($this->table, $elRow, Icon::SIZE_SMALL)->render() . '</span>';
$headerLine .= BackendUtility::getRecordTitle($this->table, $elRow, true);
// Make-copy checkbox (clicking this will reload the page with the GET var makeCopy set differently):
$onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript(array('makeCopy' => !$this->makeCopy))) . ';';
......@@ -186,7 +187,7 @@ class MoveElementController extends AbstractModule
$posMap->moveOrCopy = $this->makeCopy ? 'copy' : 'move';
$posMap->cur_sys_language = $this->sys_language;
// Headerline for the parent page: Icon, record title:
$headerLine = '<span title="' . BackendUtility::getRecordIconAltText($pageInfo, 'pages') . '">'
$headerLine = '<span ' . BackendUtility::getRecordToolTip($pageInfo, 'pages') . '>'
. $this->moduleTemplate->getIconFactory()->getIconForRecord(
'pages',
$pageInfo,
......
......@@ -18,7 +18,6 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Module\AbstractModule;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\DocumentTemplate;
use TYPO3\CMS\Backend\Tree\View\NewRecordPageTreeView;
use TYPO3\CMS\Backend\Tree\View\PagePositionMap;
use TYPO3\CMS\Backend\Utility\BackendUtility;
......@@ -179,6 +178,7 @@ class NewRecordController extends AbstractModule
$this->pagesOnly = GeneralUtility::_GP('pagesOnly');
// Setting up the context sensitive menu:
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
$this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
// Creating content
$this->content = '';
$this->content .= '<h1>'
......
......@@ -111,8 +111,8 @@ class MetaInformation
// Add icon with clickMenu, etc:
// If there IS a real page
if (is_array($pageRecord) && $pageRecord['uid']) {
$altText = BackendUtility::getRecordIconAltText($pageRecord, 'pages');
$iconImg = '<span title="' . $altText . '">' . $iconFactory->getIconForRecord('pages', $pageRecord, Icon::SIZE_SMALL)->render() . '</span>';
$toolTip = BackendUtility::getRecordToolTip($pageRecord, 'pages');
$iconImg = '<span ' . $toolTip . '>' . $iconFactory->getIconForRecord('pages', $pageRecord, Icon::SIZE_SMALL)->render() . '</span>';
// Make Icon:
$theIcon = BackendUtility::wrapClickMenuOnIcon($iconImg, 'pages', $pageRecord['uid']);
$uid = $pageRecord['uid'];
......
......@@ -15,10 +15,13 @@ namespace TYPO3\CMS\Backend\Tree\View;
*/
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Lang\LanguageService;
/**
* Position map class - generating a page tree / content element list which links for inserting (copy/move) of records.
......@@ -102,6 +105,11 @@ class PagePositionMap
*/
protected $pageTreeClassName = ElementBrowserPageTreeView::class;
/**
* @var IconFactory
*/
protected $iconFactory;
/**
* Constructor allowing to set pageTreeImplementation
*
......@@ -112,6 +120,7 @@ class PagePositionMap
if ($pageTreeClassName !== null) {
$this->pageTreeClassName = $pageTreeClassName;
}
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
}
/*************************************
......@@ -141,7 +150,6 @@ class PagePositionMap
// Create page tree, in $this->depth levels.
$pageTree->getTree($pageinfo['pid'], $this->depth);
// Initialize variables:
$saveBlankLineState = array();
$saveLatestUid = array();
$latestInvDepth = $this->depth;
// Traverse the tree:
......@@ -186,7 +194,10 @@ class PagePositionMap
$lines[] = '<span class="text-nowrap"><a href="#" onclick="' . htmlspecialchars($this->onClickEvent($prevPid, $dat['row']['pid'], 3)) . '"><i class="t3-icon fa fa-long-arrow-left" title="' . $this->insertlabel() . '"></i></a></span>';
}
// The line with the icon and title:
$lines[] = '<span class="text-nowrap">' . $dat['HTML'] . $this->linkPageTitle($this->boldTitle(htmlspecialchars(GeneralUtility::fixed_lgd_cs($dat['row']['title'], $GLOBALS['BE_USER']->uc['titleLen'])), $dat, $id), $dat['row']) . '</span>';
$toolTip = BackendUtility::getRecordToolTip($dat['row'], 'pages');
$icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord('pages', $dat['row'], Icon::SIZE_SMALL)->render() . '</span>';
$lines[] = '<span class="text-nowrap">' . $icon . $this->linkPageTitle($this->boldTitle(htmlspecialchars(GeneralUtility::fixed_lgd_cs($dat['row']['title'], $this->getBackendUser()->uc['titleLen'])), $dat, $id), $dat['row']) . '</span>';
}
// If the current page was the last in the tree:
$prev_dat = end($pageTree->tree);
......@@ -259,7 +270,7 @@ class PagePositionMap
*/
public function insertlabel()
{
return $GLOBALS['LANG']->getLL($this->l_insertNewPageHere, 1);
return $this->getLanguageService()->getLL($this->l_insertNewPageHere, 1);
}
/**
......@@ -285,7 +296,7 @@ class PagePositionMap
{
if (!isset($this->checkNewPageCache[$pid])) {
$pidInfo = BackendUtility::getRecord('pages', $pid);
$this->checkNewPageCache[$pid] = $GLOBALS['BE_USER']->isAdmin() || $GLOBALS['BE_USER']->doesUserHaveAccess($pidInfo, 8);
$this->checkNewPageCache[$pid] = $this->getBackendUser()->isAdmin() || $this->getBackendUser()->doesUserHaveAccess($pidInfo, 8);
}
return $this->checkNewPageCache[$pid];
}
......@@ -328,17 +339,17 @@ class PagePositionMap
$colPosArray = GeneralUtility::trimExplode(',', $colPosList, true);
$lines = array();
foreach ($colPosArray as $kk => $vv) {
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$pid . ($showHidden ? '' : BackendUtility::BEenableFields('tt_content')) . ' AND colPos=' . (int)$vv . ((string)$this->cur_sys_language !== '' ? ' AND sys_language_uid=' . (int)$this->cur_sys_language : '') . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting');
$res = $this->getDatabase()->exec_SELECTquery('*', 'tt_content', 'pid=' . (int)$pid . ($showHidden ? '' : BackendUtility::BEenableFields('tt_content')) . ' AND colPos=' . (int)$vv . ((string)$this->cur_sys_language !== '' ? ' AND sys_language_uid=' . (int)$this->cur_sys_language : '') . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'), '', 'sorting');
$lines[$vv] = array();
$lines[$vv][] = $this->insertPositionIcon('', $vv, $kk, $moveUid, $pid);
while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
while ($row = $this->getDatabase()->sql_fetch_assoc($res)) {
BackendUtility::workspaceOL('tt_content', $row);
if (is_array($row)) {
$lines[$vv][] = $this->wrapRecordHeader($this->getRecordHeader($row), $row);
$lines[$vv][] = $this->insertPositionIcon($row, $vv, $kk, $moveUid, $pid);
}
}
$GLOBALS['TYPO3_DB']->sql_free_result($res);
$this->getDatabase()->sql_free_result($res);
}
return $this->printRecordMap($lines, $colPosArray, $pid);
}
......@@ -356,7 +367,7 @@ class PagePositionMap
$count = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange(count($colPosArray), 1);
$backendLayout = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getSelectedBackendLayout', $pid, $this);
if (isset($backendLayout['__config']['backend_layout.'])) {
$GLOBALS['LANG']->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
$this->getLanguageService()->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf');
$table = '<div class="table-fit"><table class="table table-condensed table-bordered table-vertical-top">';
$colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
$rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
......@@ -384,7 +395,7 @@ class PagePositionMap
$head = '';
foreach ($tcaItems as $item) {
if ($item[1] == $columnKey) {
$head = $GLOBALS['LANG']->sL($item[0], true);
$head = $this->getLanguageService()->sL($item[0], true);
}
}
// Render the grid cell
......@@ -399,9 +410,9 @@ class PagePositionMap
if (isset($columnConfig['colPos']) && $head) {
$table .= '<strong>' . $this->wrapColumnHeader($head, '', '') . '</strong>';
} elseif ($columnConfig['colPos']) {
$table .= '<em>' . $this->wrapColumnHeader($GLOBALS['LANG']->getLL('noAccess'), '', '') . '</em>';
$table .= '<em>' . $this->wrapColumnHeader($this->getLanguageService()->getLL('noAccess'), '', '') . '</em>';
} else {
$table .= '<em>' . $this->wrapColumnHeader(($columnConfig['name']?: '') . ' (' . $GLOBALS['LANG']->getLL('notAssigned') . ')', '', '') . '</em>';
$table .= '<em>' . $this->wrapColumnHeader(($columnConfig['name']?: '') . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', '') . '</em>';
}
$table .= '</p>';
// Render lines
......@@ -423,7 +434,7 @@ class PagePositionMap
$row = '';
foreach ($colPosArray as $kk => $vv) {
$row .= '<td class="col-nowrap col-min" width="' . round(100 / $count) . '%">';
$row .= '<p><strong>' . $this->wrapColumnHeader($GLOBALS['LANG']->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $vv), true), $vv) . '</strong></p>';
$row .= '<p><strong>' . $this->wrapColumnHeader($this->getLanguageService()->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $vv), true), $vv) . '</strong></p>';
if (!empty($lines[$vv])) {
$row .= '<ul class="list-unstyled">';
foreach ($lines[$vv] as $line) {
......@@ -483,7 +494,7 @@ class PagePositionMap
$uid = '';
}
$cc = hexdec(substr(md5($uid . '-' . $vv . '-' . $kk), 0, 4));
return '<a href="#" onclick="' . htmlspecialchars($this->onClickInsertRecord($row, $vv, $moveUid, $pid, $this->cur_sys_language)) . '">' . '<i class="t3-icon fa fa-long-arrow-left" name="mImgEnd' . $cc . '" title="' . $GLOBALS['LANG']->getLL($this->l_insertNewRecordHere, 1) . '"></i></a>';
return '<a href="#" onclick="' . htmlspecialchars($this->onClickInsertRecord($row, $vv, $moveUid, $pid, $this->cur_sys_language)) . '">' . '<i class="t3-icon fa fa-long-arrow-left" name="mImgEnd' . $cc . '" title="' . $this->getLanguageService()->getLL($this->l_insertNewRecordHere, 1) . '"></i></a>';
}
/**
......@@ -501,9 +512,9 @@ class PagePositionMap
{
$table = 'tt_content';
if (is_array($row)) {
$location = BackendUtility::getModuleUrl('tce_db') . '&cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=-' . $row['uid'] . '&prErr=1&uPT=1&vC=' . $GLOBALS['BE_USER']->veriCode();
$location = BackendUtility::getModuleUrl('tce_db') . '&cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=-' . $row['uid'] . '&prErr=1&uPT=1&vC=' . $this->getBackendUser()->veriCode();
} else {
$location = BackendUtility::getModuleUrl('tce_db') . '&cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=' . $pid . '&data[' . $table . '][' . $moveUid . '][colPos]=' . $vv . '&prErr=1&vC=' . $GLOBALS['BE_USER']->veriCode();
$location = BackendUtility::getModuleUrl('tce_db') . '&cmd[' . $table . '][' . $moveUid . '][' . $this->moveOrCopy . ']=' . $pid . '&data[' . $table . '][' . $moveUid . '][colPos]=' . $vv . '&prErr=1&vC=' . $this->getBackendUser()->veriCode();
}
$location .= '&redirect=' . rawurlencode($this->R_URI);
// returns to prev. page
......@@ -514,7 +525,7 @@ class PagePositionMap
* Wrapping the record header (from getRecordHeader())
*
* @param string $str HTML content
* @param array $row Record array.
* @param string $row Record array.
* @return string HTML content
*/
public function wrapRecordHeader($str, $row)
......@@ -531,7 +542,8 @@ class PagePositionMap
public function getRecordHeader($row)
{
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$line = '<span title="' . BackendUtility::getRecordIconAltText($row, 'tt_content') . '">' . $iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render() . '</span>';
$toolTip = BackendUtility::getRecordToolTip($row, 'tt_content');
$line = '<span ' . $toolTip . ' title="' . BackendUtility::getRecordIconAltText($row, 'tt_content') . '">' . $iconFactory->getIconForRecord('tt_content', $row, Icon::SIZE_SMALL)->render() . '</span>';
$line .= BackendUtility::getRecordTitle('tt_content', $row, true);
return $this->wrapRecordTitle($line, $row);
}
......@@ -547,4 +559,32 @@ class PagePositionMap
{
return '<a href="' . htmlspecialchars(GeneralUtility::linkThisScript(array('uid' => (int)$row['uid'], 'moveUid' => ''))) . '">' . $str . '</a>';
}
/**
* Returns the BackendUser
*
* @return BackendUserAuthentication
*/
protected function getBackendUser()
{
return $GLOBALS['BE_USER'];
}
/**
* Returns the LanguageService
*
* @return LanguageService
*/
protected function getLanguageService()
{
return $GLOBALS['LANG'];
}
/**
* @return DatabaseConnection
*/
protected function getDatabase()
{
return $GLOBALS['TYPO3_DB'];
}
}
......@@ -1928,6 +1928,20 @@ class BackendUtility
return $includeAttrib ? 'title="' . $out . '"' : $out;
}
/**
* Returns the combined markup for Bootstraps tooltips
*
* @param array $row
* @param string $table
* @return string
*/
public static function getRecordToolTip(array $row, $table = 'pages')
{
$toolTipText = self::getRecordIconAltText($row, $table);
$toolTipCode = 'data-toggle="tooltip" data-title=" ' . str_replace(' - ', '<br>', $toolTipText) . '" data-html="true" data-placement="right"';
return $toolTipCode;
}
/**
* Returns title-attribute information for ANY record (from a table defined in TCA of course)
* The included information depends on features of the table, but if hidden, starttime, endtime and fe_group fields are configured for, information about the record status in regard to these features are is included.
......@@ -1935,7 +1949,7 @@ class BackendUtility
*
* @param array $row Table row; $row is a row from the table, $table
* @param string $table Table name
* @return string
* @return string
*/
public static function getRecordIconAltText($row, $table = 'pages')
{
......@@ -1945,7 +1959,7 @@ class BackendUtility
$out = !empty(trim($GLOBALS['TCA'][$table]['ctrl']['descriptionColumn'])) ? $row[$GLOBALS['TCA'][$table]['ctrl']['descriptionColumn']] . ' ' : '';
$ctrl = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns'];
// Uid is added
$out .= '(id=' . $row['uid'] . ')';
$out .= 'id=' . $row['uid'];
if ($table == 'pages' && $row['alias']) {
$out .= ' / ' . $row['alias'];
}
......
......@@ -208,6 +208,9 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
public function __construct()
{
$this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Tooltip');
}
/*****************************************
......@@ -2124,8 +2127,8 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
public function getIcon($table, $row)
{
// Initialization
$altText = BackendUtility::getRecordIconAltText($row, $table);
$icon = '<span title="' . $altText . '">' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
$toolTip = BackendUtility::getRecordToolTip($row, 'tt_content');
$icon = '<span ' . $toolTip . '>' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
$this->counter++;
// The icon with link
if ($this->getBackendUser()->recordEditAccessInternals($table, $row)) {
......
......@@ -887,9 +887,9 @@ class DatabaseRecordList extends AbstractDatabaseRecordList
// Incr. counter.
$this->counter++;
// The icon with link
$altText = BackendUtility::getRecordIconAltText($row, $table);
$toolTip = BackendUtility::getRecordToolTip($row, $table);
$additionalStyle = $indent ? ' style="margin-left: ' . $indent . 'px;"' : '';
$iconImg = '<span title="' . $altText . '" ' . $additionalStyle . '>'
$iconImg = '<span ' . $toolTip . ' ' . $additionalStyle . '>'
. $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render()
. '</span>';
$theIcon = $this->clickMenuEnabled ? BackendUtility::wrapClickMenuOnIcon($iconImg, $table, $row['uid']) : $iconImg;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment