[TASK] Call explicit render() on icon objects
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / View / PageLayoutView.php
index f7089dc..155e2b2 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 namespace TYPO3\CMS\Backend\View;
 
-/**
+/*
  * This file is part of the TYPO3 CMS project.
  *
  * It is free software; you can redistribute it and/or modify it under
@@ -15,106 +15,106 @@ namespace TYPO3\CMS\Backend\View;
  */
 
 use TYPO3\CMS\Backend\Controller\PageLayoutController;
-use TYPO3\CMS\Backend\Template\DocumentTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Backend\Utility\IconUtility;
 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\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Page\PageRenderer;
+use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
-use TYPO3\CMS\Lang\LanguageService;
+use TYPO3\CMS\Extbase\Service\FlexFormService;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
  * Child class for the Web > Page module
- *
- * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRecordList {
 
-       // External, static: Flags of various kinds:
-       // If TRUE, users/groups are shown in the page info box.
        /**
+        * If TRUE, users/groups are shown in the page info box.
+        *
         * @var int
         */
        public $pI_showUser = 0;
 
-       // The number of successive records to edit when showing content elements.
        /**
+        * The number of successive records to edit when showing content elements.
+        *
         * @var int
         */
        public $nextThree = 3;
 
-       // If TRUE, disables the edit-column icon for tt_content elements
        /**
+        * If TRUE, disables the edit-column icon for tt_content elements
+        *
         * @var int
         */
        public $pages_noEditColumns = 0;
 
-       // If TRUE, shows big buttons for editing page properties, moving, creating elements etc. in the columns view.
-       /**
-        * @var int
-        */
-       public $option_showBigButtons = 1;
-
-       // If TRUE, new-wizards are linked to rather than the regular new-element list.
        /**
+        * If TRUE, new-wizards are linked to rather than the regular new-element list.
+        *
         * @var int
         */
        public $option_newWizard = 1;
 
-       // If set to "1", will link a big button to content element wizard.
        /**
+        * If set to "1", will link a big button to content element wizard.
+        *
         * @var int
         */
        public $ext_function = 0;
 
-       // If TRUE, elements will have edit icons (probably this is whether the user has permission to edit the page content). Set externally.
        /**
+        * If TRUE, elements will have edit icons (probably this is whether the user has permission to edit the page content). Set externally.
+        *
         * @var int
         */
        public $doEdit = 1;
 
-       // Age prefixes for displaying times. May be set externally to localized values.
        /**
+        * Age prefixes for displaying times. May be set externally to localized values.
+        *
         * @var string
         */
        public $agePrefixes = ' min| hrs| days| yrs| min| hour| day| year';
 
-       // Array of tables to be listed by the Web > Page module in addition to the default tables.
        /**
+        * Array of tables to be listed by the Web > Page module in addition to the default tables.
+        *
         * @var array
         */
        public $externalTables = array();
 
-       // "Pseudo" Description -table name
        /**
+        * "Pseudo" Description -table name
+        *
         * @var string
         */
        public $descrTable;
 
-       // If set TRUE, the language mode of tt_content elements will be rendered with hard binding between
-       // default language content elements and their translations!
        /**
+        * If set TRUE, the language mode of tt_content elements will be rendered with hard binding between
+        * default language content elements and their translations!
+        *
         * @var bool
         */
        public $defLangBinding = FALSE;
 
-       // External, static: Configuration of tt_content element display:
        /**
+        * External, static: Configuration of tt_content element display:
+        *
         * @var array
         */
        public $tt_contentConfig = array(
-               'showInfo' => 1,
                // Boolean: Display info-marks or not
-               'showCommands' => 1,
+               'showInfo' => 1,
                // Boolean: Display up/down arrows and edit icons for tt_content records
-               'single' => 1,
-               // Boolean: If set, the content of column(s) $this->tt_contentConfig['showSingleCol'] is shown in the total width of the page
-               'showAsGrid' => 0,
-               // Boolean: If set, the content of columns is shown in grid
-               'showSingleCol' => 0,
-               // The column(s) to show if single mode (under each other)
+               'showCommands' => 1,
                'languageCols' => 0,
                'languageMode' => 0,
                'languageColsPointer' => 0,
@@ -127,8 +127,9 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                // Which columns can be accessed by current BE user
        );
 
-       // Contains icon/title of pages which are listed in the tables menu (see getTableMenu() function )
        /**
+        * Contains icon/title of pages which are listed in the tables menu (see getTableMenu() function )
+        *
         * @var array
         */
        public $activeTables = array();
@@ -142,24 +143,19 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                'next' => array()
        );
 
-       // Used to store labels for CTypes for tt_content elements
        /**
+        * Used to store labels for CTypes for tt_content elements
+        *
         * @var array
         */
        public $CType_labels = array();
 
-       // Used to store labels for the various fields in tt_content elements
-       /**
-        * @var array
-        */
-       public $itemLabels = array();
-
        /**
-        * Used to store the RTE setup of a particular page
+        * Used to store labels for the various fields in tt_content elements
         *
         * @var array
         */
-       protected $rteSetup = array();
+       public $itemLabels = array();
 
        /**
         * @var \TYPO3\CMS\Backend\Clipboard\Clipboard
@@ -174,10 +170,44 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        /**
         * User permissions
         *
-        * @var integer
+        * @var int
         */
        public $ext_CALC_PERMS;
 
+       /**
+        * Current ids page record
+        *
+        * @var array
+        */
+       protected $pageinfo;
+
+       /**
+        * Caches the available languages in a colPos
+        *
+        * @var array
+        */
+       protected $languagesInColumnCache = array();
+
+       /**
+        * Caches the amount of content elements as a matrix
+        *
+        * @var array
+        * @internal
+        */
+       protected $contentElementCache = array();
+
+       /**
+        * @var IconFactory
+        */
+       protected $iconFactory;
+
+       /**
+        * Construct to initialize class variables.
+        */
+       public function __construct() {
+               $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+       }
+
        /*****************************************
         *
         * Renderings
@@ -188,9 +218,10 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         *
         * @param string $table Table name
         * @param int $id Current page id
+        * @param string $fields
         * @return string HTML for listing.
         */
-       public function getTable($table, $id) {
+       public function getTable($table, $id, $fields = '') {
                if (isset($this->externalTables[$table])) {
                        return $this->getExternalTables($id, $table);
                } else {
@@ -270,7 +301,6 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                'cache_timeout',
                                                'php_tree_stop',
                                                'TSconfig',
-                                               'storage_pid',
                                                'is_siteroot',
                                                'fe_login_mode'
                                        );
@@ -291,13 +321,8 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        }
                        // Getting select-depth:
                        $depth = (int)$this->getPageLayoutController()->MOD_SETTINGS['pages_levels'];
-                       // Half line is drawn
-                       $theData = array();
-                       $theData['subject'] = $this->widthGif;
-                       $out .= $this->addelement(0, '', $theData);
                        // Overriding a few things:
                        $this->no_noWrap = 0;
-                       $this->oddColumnsCssClass = 'bgColor3-20';
                        // Items
                        $this->eCounter = $this->firstElementNumber;
                        // Creating elements:
@@ -327,13 +352,14 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        // Traverse fields (as set above) in order to create header values:
                        foreach ($this->fieldArray as $field) {
                                if ($editIdList && isset($GLOBALS['TCA']['pages']['columns'][$field]) && $field != 'uid' && !$this->pages_noEditColumns) {
-                                       $params = '&edit[pages][' . $editIdList . ']=edit&columnsOnly=' . $field . '&disHelp=1';
+                                       $params = '&edit[pages][' . $editIdList . ']=edit&columnsOnly=' . $field;
                                        $iTitle = sprintf(
                                                $this->getLanguageService()->getLL('editThisColumn'),
                                                rtrim(trim($this->getLanguageService()->sL(BackendUtility::getItemLabel('pages', $field))), ':')
                                        );
-                                       $eI = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath, ''))
-                                               . '" title="' . htmlspecialchars($iTitle) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
+                                       $eI = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params))
+                                               . '" title="' . htmlspecialchars($iTitle) . '">'
+                                               . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
                                } else {
                                        $eI = '';
                                }
@@ -350,9 +376,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                if (substr($field, 0, 6) == 'table_') {
                                                        $f2 = substr($field, 6);
                                                        if ($GLOBALS['TCA'][$f2]) {
-                                                               $theData[$field] = '&nbsp;' . IconUtility::getSpriteIconForRecord($f2, array(), array(
-                                                                       'title' => $this->getLanguageService()->sL($GLOBALS['TCA'][$f2]['ctrl']['title'], TRUE)
-                                                                       ));
+                                                               $theData[$field] = '&nbsp;' . '<span title="' . $this->getLanguageService()->sL($GLOBALS['TCA'][$f2]['ctrl']['title'], TRUE) . '">' . $this->iconFactory->getIconForRecord($f2, array(), Icon::SIZE_SMALL)->render() . '</span>';
                                                        }
                                                } else {
                                                        $theData[$field] = '&nbsp;&nbsp;<strong>'
@@ -361,53 +385,48 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                }
                                }
                        }
-                       // Start table:
-                       $this->oddColumnsCssClass = '';
                        // CSH:
-                       $out = BackendUtility::cshItem($this->descrTable, ('func_' . $pKey), $GLOBALS['BACK_PATH']) . '
-                               <table class="t3-table typo3-page-pages">' .
-                                       '<thead>' .
-                                               $this->addelement(1, '', $theData) .
-                                       '</thead>' .
-                                       '<tbody>' .
-                                               $out .
-                                       '</tbody>' .
-                               '</table>';
-               }
-               $this->oddColumnsCssClass = '';
+                       $out = BackendUtility::cshItem($this->descrTable, ('func_' . $pKey)) . '
+                               <div class="table-fit">
+                                       <table class="table table-striped table-hover typo3-page-pages">' .
+                                               '<thead>' .
+                                                       $this->addelement(1, '', $theData) .
+                                               '</thead>' .
+                                               '<tbody>' .
+                                                       $out .
+                                               '</tbody>' .
+                                       '</table>
+                               </div>';
+               }
                return $out;
        }
 
        /**
-        * Returns the backend layout which should be used for this page.
-        *
-        * @param int $id Uid of the current page
-        * @return bool|string Identifier of the backend layout to be used, or FALSE if none
-        * @deprecated since TYPO3 CMS 6.2, will be removed two versions later
-        */
-       public function getSelectedBackendLayoutUid($id) {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->getBackendLayoutView()->getSelectedCombinedIdentifier($id);
-       }
-
-       /**
         * Renders Content Elements from the tt_content table from page id
         *
         * @param int $id Page id
         * @return string HTML for the listing
         */
        public function getTable_tt_content($id) {
+               $backendUser = $this->getBackendUser();
+               $this->pageinfo = BackendUtility::readPageAccess($this->id, $backendUser->getPagePermsClause($this->ext_CALC_PERMS));
                $this->initializeLanguages();
                $this->initializeClipboard();
-               // Initialize:
-               $RTE = $this->getBackendUser()->isRTE();
-               $lMarg = 1;
-               $showHidden = $this->tt_contentConfig['showHidden'] ? '' : BackendUtility::BEenableFields('tt_content');
                $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode(BackendUtility::getRecordTitle('pages', BackendUtility::getRecordWSOL('pages', $id), TRUE));
-               /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
-               $pageRenderer = $this->getPageLayoutController()->doc->getPageRenderer();
-               $pageRenderer->loadExtJs();
-               $pageRenderer->addJsFile($GLOBALS['BACK_PATH'] . 'sysext/cms/layout/js/typo3pageModule.js');
+               /** @var $pageRenderer PageRenderer */
+               $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/DragDrop');
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
+               $userCanEditPage = $this->ext_CALC_PERMS & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int)$this->pageinfo['editlock'] === 0);
+               if ($this->tt_contentConfig['languageColsPointer'] > 0) {
+                       $userCanEditPage = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay');
+               }
+               $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) {
+                       PageActions.setPageId(' . (int)$this->id . ');
+                       PageActions.setCanEditPage(' . ($userCanEditPage ? 'true' : 'false') . ');
+                       PageActions.setLanguageOverlayId(' . $this->tt_contentConfig['languageColsPointer'] . ');
+                       PageActions.initializePageTitleRenaming();
+               }');
                // Get labels for CTypes and tt_content element fields in general:
                $this->CType_labels = array();
                foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) {
@@ -419,506 +438,356 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                }
                $languageColumn = array();
                $out = '';
-               // Select display mode:
-               // MULTIPLE column display mode, side by side:
-               if (!$this->tt_contentConfig['single']) {
-                       // Setting language list:
-                       $langList = $this->tt_contentConfig['sys_language_uid'];
-                       if ($this->tt_contentConfig['languageMode']) {
-                               if ($this->tt_contentConfig['languageColsPointer']) {
-                                       $langList = '0,' . $this->tt_contentConfig['languageColsPointer'];
-                               } else {
-                                       $langList = implode(',', array_keys($this->tt_contentConfig['languageCols']));
-                               }
-                               $languageColumn = array();
+
+               // Setting language list:
+               $langList = $this->tt_contentConfig['sys_language_uid'];
+               if ($this->tt_contentConfig['languageMode']) {
+                       if ($this->tt_contentConfig['languageColsPointer']) {
+                               $langList = '0,' . $this->tt_contentConfig['languageColsPointer'];
+                       } else {
+                               $langList = implode(',', array_keys($this->tt_contentConfig['languageCols']));
+                       }
+                       $languageColumn = array();
+               }
+               $langListArr = GeneralUtility::intExplode(',', $langList);
+               $defLanguageCount = array();
+               $defLangBinding = array();
+               // For each languages... :
+               // If not languageMode, then we'll only be through this once.
+               foreach ($langListArr as $lP) {
+                       $lP = (int)$lP;
+
+                       if (!isset($this->contentElementCache[$lP])) {
+                               $this->contentElementCache[$lP] = array();
                        }
-                       $langListArr = GeneralUtility::intExplode(',', $langList);
-                       $defLanguageCount = array();
-                       $defLangBinding = array();
-                       // For each languages... :
-                       // If not languageMode, then we'll only be through this once.
-                       foreach ($langListArr as $lP) {
-                               $lP = (int)$lP;
-                               if (count($langListArr) === 1 || $lP === 0) {
-                                       $showLanguage = ' AND sys_language_uid IN (' . $lP . ',-1)';
-                               } else {
-                                       $showLanguage = ' AND sys_language_uid=' . $lP;
-                               }
-                               $cList = explode(',', $this->tt_contentConfig['cols']);
-                               $content = array();
-                               $head = array();
 
-                               // Select content records per column
-                               $contentRecordsPerColumn = $this->getContentRecordsPerColumn('table', $id, array_values($cList), $showHidden . $showLanguage);
-                               // For each column, render the content into a variable:
-                               foreach ($cList as $key) {
-                                       if (!$lP) {
-                                               $defLanguageCount[$key] = array();
-                                       }
-                                       // Start wrapping div
-                                       $content[$key] .= '<div class="t3-page-ce-wrapper';
-                                       if (count($contentRecordsPerColumn[$key]) === 0) {
-                                               $content[$key] .= ' t3-page-ce-empty';
-                                       }
-                                       $content[$key] .= '">';
-                                       // Add new content at the top most position
-                                       $content[$key] .= '
-                                       <div class="t3-page-ce" id="' . str_replace('.', '', uniqid('', TRUE)) . '">
-                                               <div class="t3-page-ce-dropzone" id="colpos-' . $key . '-' . 'page-' . $id . '-' . uniqid('', TRUE) . '">
-                                                       <div class="t3-page-ce-wrapper-new-ce">
-                                                               <a href="#" onclick="' . htmlspecialchars($this->newContentElementOnClick($id, $key, $lP))
-                                                                       . '" title="' . $this->getLanguageService()->getLL('newRecordHere', TRUE) . '">'
-                                                                       . IconUtility::getSpriteIcon('actions-document-new') . '</a>
-                                                       </div>
-                                               </div>
-                                       </div>
-                                       ';
-                                       $editUidList = '';
-                                       $rowArr = $contentRecordsPerColumn[$key];
-                                       $this->generateTtContentDataArray($rowArr);
-                                       foreach ((array) $rowArr as $rKey => $row) {
-                                               if ($this->tt_contentConfig['languageMode']) {
-                                                       $languageColumn[$key][$lP] = $head[$key] . $content[$key];
-                                                       if (!$this->defLangBinding) {
-                                                               $languageColumn[$key][$lP] .= $this->newLanguageButton(
-                                                                       $this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP),
-                                                                       $lP
-                                                               );
-                                                       }
-                                               }
-                                               if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
-                                                       $singleElementHTML = '';
-                                                       if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) {
-                                                               $defLanguageCount[$key][] = $row['uid'];
-                                                       }
-                                                       $editUidList .= $row['uid'] . ',';
-                                                       $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0;
-                                                       if (!$this->tt_contentConfig['languageMode']) {
-                                                               $singleElementHTML .= '<div class="t3-page-ce-dragitem" id="' . str_replace('.', '', uniqid('', TRUE)) . '">';
-                                                       }
-                                                       $singleElementHTML .= $this->tt_content_drawHeader(
-                                                               $row,
-                                                               $this->tt_contentConfig['showInfo'] ? 15 : 5,
-                                                               $disableMoveAndNewButtons,
-                                                               TRUE,
-                                                               !$this->tt_contentConfig['languageMode']
-                                                       );
-                                                       $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext');
-                                                       $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>'
-                                                               . $this->tt_content_drawItem($row, $isRTE) . '</div>';
-                                                       $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div>'
-                                                               . $this->tt_content_drawFooter($row);
-                                                       // NOTE: this is the end tag for <div class="t3-page-ce-body">
-                                                       // because of bad (historic) conception, starting tag has to be placed inside tt_content_drawHeader()
-                                                       $singleElementHTML .= '</div>';
-                                                       $statusHidden = $this->isDisabled('tt_content', $row) ? ' t3-page-ce-hidden' : '';
-                                                       $singleElementHTML = '<div class="t3-page-ce' . $statusHidden . '" id="element-tt_content-'
-                                                               . $row['uid'] . '">' . $singleElementHTML . '</div>';
-                                                       if ($this->tt_contentConfig['languageMode']) {
-                                                               $singleElementHTML .= '<div class="t3-page-ce">';
-                                                       }
-                                                       $singleElementHTML .= '<div class="t3-page-ce-dropzone" id="colpos-' . $key . '-' . 'page-' . $id .
-                                                               '-' . str_replace('.', '', uniqid('', TRUE)) . '">';
-                                                       // Add icon "new content element below"
-                                                       if (!$disableMoveAndNewButtons) {
-                                                               // New content element:
-                                                               if ($this->option_newWizard) {
-                                                                       $onClick = 'window.location.href=\'db_new_content_el.php?id=' . $row['pid']
-                                                                               . '&sys_language_uid=' . $row['sys_language_uid'] . '&colPos=' . $row['colPos']
-                                                                               . '&uid_pid=' . -$row['uid'] .
-                                                                               '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';';
-                                                               } else {
-                                                                       $params = '&edit[tt_content][' . -$row['uid'] . ']=new';
-                                                                       $onClick = BackendUtility::editOnClick($params, $this->backPath);
-                                                               }
-                                                               $singleElementHTML .= '
-                                                                       <div class="t3-page-ce-wrapper-new-ce">
-                                                                               <a href="#" onclick="' . htmlspecialchars($onClick) . '" title="'
-                                                                                       . $this->getLanguageService()->getLL('newRecordHere', TRUE) . '">'
-                                                                                       . IconUtility::getSpriteIcon('actions-document-new') . '</a>
-                                                                       </div>
-                                                               ';
-                                                       }
-                                                       $singleElementHTML .= '</div></div>';
-                                                       if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) {
-                                                               $defLangBinding[$key][$lP][$row[$lP ? 'l18n_parent' : 'uid']] = $singleElementHTML;
-                                                       } else {
-                                                               $content[$key] .= $singleElementHTML;
-                                                       }
-                                               } else {
-                                                       unset($rowArr[$rKey]);
-                                               }
-                                       }
-                                       $content[$key] .= '</div>';
-                                       // Add new-icon link, header:
-                                       $newP = $this->newContentElementOnClick($id, $key, $lP);
-                                       $colTitle = BackendUtility::getProcessedValue('tt_content', 'colPos', $key);
-                                       $tcaItems = GeneralUtility::callUserFunction('TYPO3\\CMS\\Backend\\View\\BackendLayoutView->getColPosListItemsParsed', $id, $this);
-                                       foreach ($tcaItems as $item) {
-                                               if ($item[1] == $key) {
-                                                       $colTitle = $this->getLanguageService()->sL($item[0]);
-                                               }
-                                       }
+                       if (count($langListArr) === 1 || $lP === 0) {
+                               $showLanguage = ' AND sys_language_uid IN (' . $lP . ',-1)';
+                       } else {
+                               $showLanguage = ' AND sys_language_uid=' . $lP;
+                       }
+                       $cList = explode(',', $this->tt_contentConfig['cols']);
+                       $content = array();
+                       $head = array();
+
+                       // Select content records per column
+                       $contentRecordsPerColumn = $this->getContentRecordsPerColumn('table', $id, array_values($cList), $showLanguage);
+                       // For each column, render the content into a variable:
+                       foreach ($cList as $key) {
+                               if (!isset($this->contentElementCache[$lP][$key])) {
+                                       $this->contentElementCache[$lP][$key] = array();
+                               }
 
-                                       $pasteP = array('colPos' => $key, 'sys_language_uid' => $lP);
-                                       $editParam = $this->doEdit && count($rowArr)
-                                               ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc
-                                               : '';
-                                       $head[$key] .= $this->tt_content_drawColHeader($colTitle, $editParam, $newP, $pasteP);
+                               if (!$lP) {
+                                       $defLanguageCount[$key] = array();
+                               }
+                               // Start wrapping div
+                               $content[$key] .= '<div data-colpos="' . $key . '" data-language-uid="' . $lP . '" class="t3js-sortable t3js-sortable-lang t3js-sortable-lang-' . $lP . ' t3-page-ce-wrapper';
+                               if (empty($contentRecordsPerColumn[$key])) {
+                                       $content[$key] .= ' t3-page-ce-empty';
                                }
-                               // For each column, fit the rendered content into a table cell:
-                               $out = '';
-                               if ($this->tt_contentConfig['languageMode']) {
-                                       // in language mode process the content elements, but only fill $languageColumn. output will be generated later
-                                       foreach ($cList as $key) {
+                               $content[$key] .= '">';
+                               // Add new content at the top most position
+                               $link = '';
+                               if ($this->getPageLayoutController()->pageIsNotLockedForEditors()) {
+                                       $link = '<a href="#" onclick="' . htmlspecialchars($this->newContentElementOnClick($id, $key, $lP))
+                                               . '" title="' . $this->getLanguageService()->getLL('newContentElement', TRUE) . '" class="btn btn-default btn-sm">'
+                                               . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render()
+                                               . ' '
+                                               . $this->getLanguageService()->getLL('content', TRUE) . '</a>';
+                               }
+                               $content[$key] .= '
+                               <div class="t3-page-ce t3js-page-ce" data-page="' . (int)$id . '" id="' . StringUtility::getUniqueId() . '">
+                                       <div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id . '-' . StringUtility::getUniqueId() . '">'
+                                               . $link
+                                       . '</div>
+                                       <div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div>
+                               </div>
+                               ';
+                               $editUidList = '';
+                               $rowArr = $contentRecordsPerColumn[$key];
+                               $this->generateTtContentDataArray($rowArr);
+
+                               foreach ((array)$rowArr as $rKey => $row) {
+                                       $this->contentElementCache[$lP][$key][$row['uid']] = $row;
+                                       if ($this->tt_contentConfig['languageMode']) {
                                                $languageColumn[$key][$lP] = $head[$key] . $content[$key];
                                                if (!$this->defLangBinding) {
                                                        $languageColumn[$key][$lP] .= $this->newLanguageButton(
                                                                $this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP),
-                                                               $lP
+                                                               $lP,
+                                                               $key
                                                        );
                                                }
                                        }
-                               } else {
-                                       $backendLayout = $this->getBackendLayoutView()->getSelectedBackendLayout($this->id);
-                                       // GRID VIEW:
-                                       $grid = '<div class="t3-gridContainer"><table border="0" cellspacing="0" cellpadding="0" width="100%" height="100%" class="t3-page-columns t3-gridTable">';
-                                       // Add colgroups
-                                       $colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
-                                       $rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
-                                       $grid .= '<colgroup>';
-                                       for ($i = 0; $i < $colCount; $i++) {
-                                               $grid .= '<col style="width:' . 100 / $colCount . '%"></col>';
-                                       }
-                                       $grid .= '</colgroup>';
-                                       // Cycle through rows
-                                       for ($row = 1; $row <= $rowCount; $row++) {
-                                               $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
-                                               if (!isset($rowConfig)) {
-                                                       continue;
+                                       if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
+                                               $singleElementHTML = '';
+                                               if (!$lP && ($this->defLangBinding || $row['sys_language_uid'] != -1)) {
+                                                       $defLanguageCount[$key][] = (isset($row['_ORIG_uid']) ? $row['_ORIG_uid'] : $row['uid']);
                                                }
-                                               $grid .= '<tr>';
-                                               for ($col = 1; $col <= $colCount; $col++) {
-                                                       $columnConfig = $rowConfig['columns.'][$col . '.'];
-                                                       if (!isset($columnConfig)) {
-                                                               continue;
-                                                       }
-                                                       // Which tt_content colPos should be displayed inside this cell
-                                                       $columnKey = (int)$columnConfig['colPos'];
-                                                       // Render the grid cell
-                                                       $colSpan = (int)$columnConfig['colspan'];
-                                                       $rowSpan = (int)$columnConfig['rowspan'];
-                                                       $grid .= '<td valign="top"' .
-                                                               ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
-                                                               ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
-                                                               ' class="t3-gridCell t3-page-column t3-page-column-' . $columnKey .
-                                                               ((!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '') ? ' t3-gridCell-unassigned' : '') .
-                                                               ((isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey]) || !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos']) ? ' t3-gridCell-restricted' : '') .
-                                                               ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') .
-                                                               ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">';
-
-                                                       // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
-                                                       // If not, a new header without any buttons will be generated.
-                                                       if (
-                                                               isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey]
-                                                               && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
-                                                       ) {
-                                                               $grid .= $head[$columnKey] . $content[$columnKey];
-                                                       } elseif (
-                                                               isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
-                                                               && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
-                                                       ) {
-                                                               $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('noAccess'), '', '');
-                                                       } elseif (
-                                                               isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
-                                                               && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
-                                                       ) {
-                                                               $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) .
-                                                                       ' (' . $this->getLanguageService()->getLL('noAccess') . ')', '', '');
-                                                       } elseif (isset($columnConfig['name']) && strlen($columnConfig['name']) > 0) {
-                                                               $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name'])
-                                                                       . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', '');
+                                               $editUidList .= $row['uid'] . ',';
+                                               $disableMoveAndNewButtons = $this->defLangBinding && $lP > 0;
+                                               if (!$this->tt_contentConfig['languageMode']) {
+                                                       $singleElementHTML .= '<div class="t3-page-ce-dragitem" id="' . StringUtility::getUniqueId() . '">';
+                                               }
+                                               $singleElementHTML .= $this->tt_content_drawHeader(
+                                                       $row,
+                                                       $this->tt_contentConfig['showInfo'] ? 15 : 5,
+                                                       $disableMoveAndNewButtons,
+                                                       TRUE,
+                                                       !$this->tt_contentConfig['languageMode']
+                                               );
+                                               $innerContent = '<div ' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . '>'
+                                                       . $this->tt_content_drawItem($row) . '</div>';
+                                               $singleElementHTML .= '<div class="t3-page-ce-body-inner">' . $innerContent . '</div>'
+                                                       . $this->tt_content_drawFooter($row);
+                                               $isDisabled = $this->isDisabled('tt_content', $row);
+                                               $statusHidden = $isDisabled ? ' t3-page-ce-hidden t3js-hidden-record' : '';
+                                               $displayNone = !$this->tt_contentConfig['showHidden'] && $isDisabled ? ' style="display: none;"' : '';
+                                               $singleElementHTML = '<div class="t3-page-ce t3js-page-ce t3js-page-ce-sortable ' . $statusHidden . '" id="element-tt_content-'
+                                                       . $row['uid'] . '" data-table="tt_content" data-uid="' . $row['uid'] . '"' . $displayNone . '>' . $singleElementHTML . '</div>';
+
+                                               if ($this->tt_contentConfig['languageMode']) {
+                                                       $singleElementHTML .= '<div class="t3-page-ce t3js-page-ce">';
+                                               }
+                                               $singleElementHTML .= '<div class="t3js-page-new-ce t3-page-ce-wrapper-new-ce" id="colpos-' . $key . '-' . 'page-' . $id .
+                                                       '-' . StringUtility::getUniqueId() . '">';
+                                               // Add icon "new content element below"
+                                               if (!$disableMoveAndNewButtons && $this->getPageLayoutController()->pageIsNotLockedForEditors()) {
+                                                       // New content element:
+                                                       if ($this->option_newWizard) {
+                                                               $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('new_content_element') . '&id=' . $row['pid']
+                                                                       . '&sys_language_uid=' . $row['sys_language_uid'] . '&colPos=' . $row['colPos']
+                                                                       . '&uid_pid=' . -$row['uid'] .
+                                                                       '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';';
                                                        } else {
-                                                               $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('notAssigned'), '', '');
+                                                               $params = '&edit[tt_content][' . -$row['uid'] . ']=new';
+                                                               $onClick = BackendUtility::editOnClick($params);
                                                        }
-
-                                                       $grid .= '</td>';
+                                                       $singleElementHTML .= '
+                                                               <a href="#" onclick="' . htmlspecialchars($onClick) . '" title="'
+                                                                       . $this->getLanguageService()->getLL('newContentElement', TRUE) . '" class="btn btn-default btn-sm">'
+                                                                       . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render()
+                                                                       . ' '
+                                                                       . $this->getLanguageService()->getLL('content', TRUE) . '</a>
+                                                       ';
+                                               }
+                                               $singleElementHTML .= '</div></div><div class="t3-page-ce-dropzone-available t3js-page-ce-dropzone-available"></div></div>';
+                                               if ($this->defLangBinding && $this->tt_contentConfig['languageMode']) {
+                                                       $defLangBinding[$key][$lP][$row[$lP ? 'l18n_parent' : 'uid']] = $singleElementHTML;
+                                               } else {
+                                                       $content[$key] .= $singleElementHTML;
                                                }
-                                               $grid .= '</tr>';
-                                       }
-                                       $out .= $grid . '</table></div>';
-                               }
-                               // CSH:
-                               $out .= BackendUtility::cshItem($this->descrTable, 'columns_multi', $GLOBALS['BACK_PATH']);
-                       }
-                       // If language mode, then make another presentation:
-                       // Notice that THIS presentation will override the value of $out!
-                       // But it needs the code above to execute since $languageColumn is filled with content we need!
-                       if ($this->tt_contentConfig['languageMode']) {
-                               // Get language selector:
-                               $languageSelector = $this->languageSelector($id);
-                               // Reset out - we will make new content here:
-                               $out = '';
-                               // Traverse languages found on the page and build up the table displaying them side by side:
-                               $cCont = array();
-                               $sCont = array();
-                               foreach ($langListArr as $lP) {
-                                       // Header:
-                                       $lP = (int)$lP;
-                                       $cCont[$lP] = '
-                                               <td valign="top" class="t3-page-lang-column">
-                                                       <h3>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h3>
-                                               </td>';
-
-                                       // "View page" icon is added:
-                                       $onClick = BackendUtility::viewOnClick($this->id, $this->backPath, BackendUtility::BEgetRootLine($this->id), '', '', ('&L=' . $lP));
-                                       $viewLink = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . IconUtility::getSpriteIcon('actions-document-view') . '</a>';
-                                       // Language overlay page header:
-                                       if ($lP) {
-                                               list($lpRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . $lP);
-                                               BackendUtility::workspaceOL('pages_language_overlay', $lpRecord);
-                                               $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP;
-                                               $lPLabel = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon(
-                                                       IconUtility::getSpriteIconForRecord('pages_language_overlay', $lpRecord),
-                                                       'pages_language_overlay',
-                                                       $lpRecord['uid']
-                                               ) . $viewLink . ($this->getBackendUser()->check('tables_modify', 'pages_language_overlay')
-                                                               ? '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath))
-                                                                       . '" title="' . $this->getLanguageService()->getLL('edit', TRUE) . '">'
-                                                                       . IconUtility::getSpriteIcon('actions-document-open') . '</a>'
-                                                               : ''
-                                                       ) . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20));
                                        } else {
-                                               $lPLabel = $viewLink;
+                                               unset($rowArr[$rKey]);
                                        }
-                                       $sCont[$lP] = '
-                                               <td nowrap="nowrap" class="t3-page-lang-column t3-page-lang-label">' . $lPLabel . '</td>';
                                }
-                               // Add headers:
-                               $out .= '<tr>' . implode($cCont) . '</tr>';
-                               $out .= '<tr>' . implode($sCont) . '</tr>';
-                               // Traverse previously built content for the columns:
-                               foreach ($languageColumn as $cKey => $cCont) {
-                                       $out .= '
-                                       <tr>
-                                               <td valign="top" class="t3-gridCell t3-page-column t3-page-lang-column">' . implode(('</td>' . '
-                                               <td valign="top" class="t3-gridCell t3-page-column t3-page-lang-column">'), $cCont) . '</td>
-                                       </tr>';
-                                       if ($this->defLangBinding) {
-                                               // "defLangBinding" mode
-                                               foreach ($defLanguageCount[$cKey] as $defUid) {
-                                                       $cCont = array();
-                                                       foreach ($langListArr as $lP) {
-                                                               $cCont[] = $defLangBinding[$cKey][$lP][$defUid] . $this->newLanguageButton(
-                                                                       $this->getNonTranslatedTTcontentUids(array($defUid), $id, $lP),
-                                                                       $lP
-                                                               );
-                                                       }
-                                                       $out .= '
-                                                       <tr>
-                                                               <td valign="top" class="t3-page-lang-column">' . implode(('</td>' . '
-                                                               <td valign="top" class="t3-page-lang-column">'), $cCont) . '</td>
-                                                       </tr>';
-                                               }
-                                               // Create spacer:
-                                               $cCont = array_fill(0, count($langListArr), '&nbsp;');
-                                               $out .= '
-                                               <tr>
-                                                       <td valign="top" class="t3-page-lang-column">' . implode(('</td>' . '
-                                                       <td valign="top" class="t3-page-lang-column">'), $cCont) . '</td>
-                                               </tr>';
+                               $content[$key] .= '</div>';
+                               // Add new-icon link, header:
+                               $newP = $this->newContentElementOnClick($id, $key, $lP);
+                               $colTitle = BackendUtility::getProcessedValue('tt_content', 'colPos', $key);
+                               $tcaItems = GeneralUtility::callUserFunction(\TYPO3\CMS\Backend\View\BackendLayoutView::class . '->getColPosListItemsParsed', $id, $this);
+                               foreach ($tcaItems as $item) {
+                                       if ($item[1] == $key) {
+                                               $colTitle = $this->getLanguageService()->sL($item[0]);
                                        }
                                }
-                               // Finally, wrap it all in a table and add the language selector on top of it:
-                               $out = $languageSelector . '
-                                       <div class="t3-lang-gridContainer">
-                                               <table cellpadding="0" cellspacing="0" class="t3-page-langMode">
-                                                       ' . $out . '
-                                               </table>
-                                       </div>';
-                               // CSH:
-                               $out .= BackendUtility::cshItem($this->descrTable, 'language_list', $GLOBALS['BACK_PATH']);
+
+                               $pasteP = array('colPos' => $key, 'sys_language_uid' => $lP);
+                               $editParam = $this->doEdit && !empty($rowArr)
+                                       ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc
+                                       : '';
+                               $head[$key] .= $this->tt_content_drawColHeader($colTitle, $editParam, $newP, $pasteP);
                        }
-               } else {
-                       // SINGLE column mode (columns shown beneath each other):
-                       if ($this->tt_contentConfig['sys_language_uid'] == 0 || !$this->defLangBinding) {
-                               // Initialize:
-                               if ($this->defLangBinding && $this->tt_contentConfig['sys_language_uid'] == 0) {
-                                       $showLanguage = ' AND sys_language_uid IN (0,-1)';
-                                       $lP = 0;
-                               } else {
-                                       $showLanguage = ' AND sys_language_uid=' . $this->tt_contentConfig['sys_language_uid'];
-                                       $lP = $this->tt_contentConfig['sys_language_uid'];
+                       // For each column, fit the rendered content into a table cell:
+                       $out = '';
+                       if ($this->tt_contentConfig['languageMode']) {
+                               // in language mode process the content elements, but only fill $languageColumn. output will be generated later
+                               $sortedLanguageColumn = array();
+                               foreach ($cList as $key) {
+                                       $languageColumn[$key][$lP] = $head[$key] . $content[$key];
+                                       if (!$this->defLangBinding) {
+                                               $languageColumn[$key][$lP] .= $this->newLanguageButton(
+                                                       $this->getNonTranslatedTTcontentUids($defLanguageCount[$key], $id, $lP),
+                                                       $lP,
+                                                       $key
+                                               );
+                                       }
+                                       // We sort $languageColumn again according to $cList as it may contain data already from above.
+                                       $sortedLanguageColumn[$key] = $languageColumn[$key];
                                }
-                               $cList = explode(',', $this->tt_contentConfig['showSingleCol']);
-                               $out = '';
-                               // Expand the table to some preset dimensions:
-                               $out .= '
-                                       <tr>
-                                               <td><img src="clear.gif" width="' . $lMarg . '" height="1" alt="" /></td>
-                                               <td valign="top"><img src="clear.gif" width="150" height="1" alt="" /></td>
-                                               <td><img src="clear.gif" width="10" height="1" alt="" /></td>
-                                               <td valign="top"><img src="clear.gif" width="300" height="1" alt="" /></td>
-                                       </tr>';
-
-                               // Select content records per column
-                               $contentRecordsPerColumn = $this->getContentRecordsPerColumn('tt_content', $id, array_values($cList), $showHidden . $showLanguage);
-                               // Traverse columns to display top-on-top
-                               foreach ($cList as $counter => $key) {
-                                       $c = 0;
-                                       $rowArr = $contentRecordsPerColumn[$key];
-                                       $this->generateTtContentDataArray($rowArr);
-                                       $numberOfContentElementsInColumn = count($rowArr);
-                                       $rowOut = '';
-                                       // If it turns out that there are not content elements in the column, then display a big button which links directly to the wizard script:
-                                       if ($this->doEdit && $this->option_showBigButtons && !(int)$key && $numberOfContentElementsInColumn == 0) {
-                                               $onClick = 'window.location.href=\'db_new_content_el.php?id=' . $id . '&colPos=' . (int)$key
-                                                       . '&sys_language_uid=' . $lP . '&uid_pid=' . $id . '&returnUrl='
-                                                       . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';';
-                                               $theNewButton = $this->getPageLayoutController()->doc->t3Button($onClick, $this->getLanguageService()->getLL('newPageContent'));
-                                               $theNewButton = '<img src="clear.gif" width="1" height="5" alt="" /><br />' . $theNewButton;
-                                       } else {
-                                               $theNewButton = '';
+                               $languageColumn = $sortedLanguageColumn;
+                       } else {
+                               $backendLayout = $this->getBackendLayoutView()->getSelectedBackendLayout($this->id);
+                               // GRID VIEW:
+                               $grid = '<div class="t3-grid-container"><table border="0" cellspacing="0" cellpadding="0" width="100%" height="100%" class="t3-page-columns t3-grid-table t3js-page-columns">';
+                               // Add colgroups
+                               $colCount = (int)$backendLayout['__config']['backend_layout.']['colCount'];
+                               $rowCount = (int)$backendLayout['__config']['backend_layout.']['rowCount'];
+                               $grid .= '<colgroup>';
+                               for ($i = 0; $i < $colCount; $i++) {
+                                       $grid .= '<col style="width:' . 100 / $colCount . '%"></col>';
+                               }
+                               $grid .= '</colgroup>';
+                               // Cycle through rows
+                               for ($row = 1; $row <= $rowCount; $row++) {
+                                       $rowConfig = $backendLayout['__config']['backend_layout.']['rows.'][$row . '.'];
+                                       if (!isset($rowConfig)) {
+                                               continue;
                                        }
-                                       $editUidList = '';
-                                       // Traverse any selected elements:
-                                       foreach ($rowArr as $rKey => $row) {
-                                               if (is_array($row) && !VersionState::cast($row['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
-                                                       $c++;
-                                                       $editUidList .= $row['uid'] . ',';
-                                                       $isRTE = $RTE && $this->isRTEforField('tt_content', $row, 'bodytext');
-                                                       // Create row output:
-                                                       $rowOut .= '
-                                                               <tr>
-                                                                       <td></td>
-                                                                       <td valign="top">' . $this->tt_content_drawHeader($row) . '</td>
-                                                                       <td>&nbsp;</td>
-                                                                       <td' . ($row['_ORIG_uid'] ? ' class="ver-element"' : '') . ' valign="top">'
-                                                                               . $this->tt_content_drawItem($row, $isRTE) . '</td>
-                                                               </tr>';
-                                                       // If the element was not the last element, add a divider line:
-                                                       if ($c != $numberOfContentElementsInColumn) {
-                                                               $rowOut .= '
-                                                               <tr>
-                                                                       <td></td>
-                                                                       <td colspan="3"><img'
-                                                                       . IconUtility::skinImg($this->backPath, 'gfx/stiblet_medium2.gif', 'width="468" height="1"')
-                                                                       . ' class="c-divider" alt="" /></td>
-                                                               </tr>';
-                                                       }
+                                       $grid .= '<tr>';
+                                       for ($col = 1; $col <= $colCount; $col++) {
+                                               $columnConfig = $rowConfig['columns.'][$col . '.'];
+                                               if (!isset($columnConfig)) {
+                                                       continue;
+                                               }
+                                               // Which tt_content colPos should be displayed inside this cell
+                                               $columnKey = (int)$columnConfig['colPos'];
+                                               // Render the grid cell
+                                               $colSpan = (int)$columnConfig['colspan'];
+                                               $rowSpan = (int)$columnConfig['rowspan'];
+                                               $grid .= '<td valign="top"' .
+                                                       ($colSpan > 0 ? ' colspan="' . $colSpan . '"' : '') .
+                                                       ($rowSpan > 0 ? ' rowspan="' . $rowSpan . '"' : '') .
+                                                       ' data-colpos="' . (int)$columnConfig['colPos'] . '" data-language-uid="' . $lP . '" class="t3js-page-lang-column-' . $lP . ' t3js-page-column t3-grid-cell t3-page-column t3-page-column-' . $columnKey .
+                                                       ((!isset($columnConfig['colPos']) || $columnConfig['colPos'] === '') ? ' t3-grid-cell-unassigned' : '') .
+                                                       ((isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && !$head[$columnKey]) || !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos']) ? ' t3-grid-cell-restricted' : '') .
+                                                       ($colSpan > 0 ? ' t3-gridCell-width' . $colSpan : '') .
+                                                       ($rowSpan > 0 ? ' t3-gridCell-height' . $rowSpan : '') . '">';
+
+                                               // Draw the pre-generated header with edit and new buttons if a colPos is assigned.
+                                               // If not, a new header without any buttons will be generated.
+                                               if (
+                                                       isset($columnConfig['colPos']) && $columnConfig['colPos'] !== '' && $head[$columnKey]
+                                                       && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
+                                               ) {
+                                                       $grid .= $head[$columnKey] . $content[$columnKey];
+                                               } elseif (
+                                                       isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
+                                                       && GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
+                                               ) {
+                                                       $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('noAccess'), '', '');
+                                               } elseif (
+                                                       isset($columnConfig['colPos']) && $columnConfig['colPos'] !== ''
+                                                       && !GeneralUtility::inList($this->tt_contentConfig['activeCols'], $columnConfig['colPos'])
+                                               ) {
+                                                       $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name']) .
+                                                               ' (' . $this->getLanguageService()->getLL('noAccess') . ')', '', '');
+                                               } elseif (isset($columnConfig['name']) && $columnConfig['name'] !== '') {
+                                                       $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->sL($columnConfig['name'])
+                                                               . ' (' . $this->getLanguageService()->getLL('notAssigned') . ')', '', '');
                                                } else {
-                                                       unset($rowArr[$rKey]);
+                                                       $grid .= $this->tt_content_drawColHeader($this->getLanguageService()->getLL('notAssigned'), '', '');
                                                }
-                                       }
-                                       // Add spacer between sections in the vertical list
-                                       if ($counter) {
-                                               $out .= '
-                                                       <tr>
-                                                               <td></td>
-                                                               <td colspan="3"><br /><br /><br /><br /></td>
-                                                       </tr>';
-                                       }
-                                       // Add section header:
-                                       $newP = $this->newContentElementOnClick($id, $key, $this->tt_contentConfig['sys_language_uid']);
-                                       $pasteP = array('colPos' => $key, 'sys_language_uid' => $this->tt_contentConfig['sys_language_uid']);
-                                       $out .= '
 
-                                               <!-- Column header: -->
-                                               <tr>
-                                                       <td></td>
-                                                       <td valign="top" colspan="3">' . $this->tt_content_drawColHeader(
-                                                               BackendUtility::getProcessedValue('tt_content', 'colPos', $key),
-                                                               $this->doEdit && count($rowArr) ? '&edit[tt_content][' . $editUidList . ']=edit' . $pageTitleParamForAltDoc : '',
-                                                               $newP,
-                                                               $pasteP
-                                                       ) . $theNewButton . '<br /></td>
-                                               </tr>';
-                                       // Finally, add the content from the records in this column:
-                                       $out .= $rowOut;
+                                               $grid .= '</td>';
+                                       }
+                                       $grid .= '</tr>';
                                }
-                               // Finally, wrap all table rows in one, big table:
-                               $out = '
-                                       <table border="0" cellpadding="0" cellspacing="0" width="400" class="typo3-page-columnsMode">
-                                               ' . $out . '
-                                       </table>';
-                               // CSH:
-                               $out .= BackendUtility::cshItem($this->descrTable, 'columns_single', $GLOBALS['BACK_PATH']);
-                       } else {
-                               $out = '<br/><br/>' . $this->getPageLayoutController()->doc->icons(1)
-                                       . 'Sorry, you cannot view a single language in this localization mode (Default Language Binding is enabled)<br/><br/>';
+                               $out .= $grid . '</table></div>';
                        }
+                       // CSH:
+                       $out .= BackendUtility::cshItem($this->descrTable, 'columns_multi');
                }
-               // Add the big buttons to page:
-               if ($this->option_showBigButtons) {
-                       $bArray = array();
-                       if (!$this->getPageLayoutController()->current_sys_language) {
-                               if ($this->ext_CALC_PERMS & 2) {
-                                       $bArray[0] = $this->getPageLayoutController()->doc->t3Button(
-                                               BackendUtility::editOnClick('&edit[pages][' . $id . ']=edit', $this->backPath, ''),
-                                               $this->getLanguageService()->getLL('editPageProperties')
-                                       );
+               // If language mode, then make another presentation:
+               // Notice that THIS presentation will override the value of $out!
+               // But it needs the code above to execute since $languageColumn is filled with content we need!
+               if ($this->tt_contentConfig['languageMode']) {
+                       // Get language selector:
+                       $languageSelector = $this->languageSelector($id);
+                       // Reset out - we will make new content here:
+                       $out = '';
+                       // Traverse languages found on the page and build up the table displaying them side by side:
+                       $cCont = array();
+                       $sCont = array();
+                       foreach ($langListArr as $lP) {
+                               // Header:
+                               $lP = (int)$lP;
+                               $cCont[$lP] = '
+                                       <td valign="top" class="t3-page-column" data-language-uid="' . $lP . '">
+                                               <h2>' . htmlspecialchars($this->tt_contentConfig['languageCols'][$lP]) . '</h2>
+                                       </td>';
+
+                               // "View page" icon is added:
+                               $viewLink = '';
+                               if (!VersionState::cast($this->getPageLayoutController()->pageinfo['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
+                                       $onClick = BackendUtility::viewOnClick($this->id, '', BackendUtility::BEgetRootLine($this->id), '', '', ('&L=' . $lP));
+                                       $viewLink = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', TRUE) . '">' . $this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL)->render() . '</a>';
                                }
-                       } else {
-                               if ($this->doEdit && $this->getBackendUser()->check('tables_modify', 'pages_language_overlay')) {
-                                       list($languageOverlayRecord) = BackendUtility::getRecordsByField(
+                               // Language overlay page header:
+                               if ($lP) {
+                                       list($lpRecord) = BackendUtility::getRecordsByField('pages_language_overlay', 'pid', $id, 'AND sys_language_uid=' . $lP);
+                                       BackendUtility::workspaceOL('pages_language_overlay', $lpRecord);
+                                       $params = '&edit[pages_language_overlay][' . $lpRecord['uid'] . ']=edit&overrideVals[pages_language_overlay][sys_language_uid]=' . $lP;
+                                       $lPLabel = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon(
+                                               $this->iconFactory->getIconForRecord('pages_language_overlay', $lpRecord, Icon::SIZE_SMALL)->render(),
                                                'pages_language_overlay',
-                                               'pid',
-                                               $id,
-                                               'AND sys_language_uid=' . (int)$this->getPageLayoutController()->current_sys_language
-                                       );
-                                       $bArray[0] = $this->getPageLayoutController()->doc->t3Button(
-                                               BackendUtility::editOnClick('&edit[pages_language_overlay][' . $languageOverlayRecord['uid'] . ']=edit',
-                                                       $this->backPath, ''),
-                                               $this->getLanguageService()->getLL('editPageProperties_curLang')
-                                       );
+                                               $lpRecord['uid']
+                                       ) . $viewLink . ($this->getBackendUser()->check('tables_modify', 'pages_language_overlay')
+                                                       ? '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params))
+                                                               . '" title="' . $this->getLanguageService()->getLL('edit', TRUE) . '">'
+                                                               . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'
+                                                       : ''
+                                               ) . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20));
+                               } else {
+                                       $params = '&edit[pages][' . $this->id . ']=edit';
+                                       $lPLabel = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon(
+                                                       $this->iconFactory->getIconForRecord('pages', $this->pageRecord, Icon::SIZE_SMALL)->render(),
+                                                       'pages',
+                                                       $this->id
+                                               ) . $viewLink . ($this->getBackendUser()->check('tables_modify', 'pages_language_overlay')
+                                                       ? '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params))
+                                                       . '" title="' . $this->getLanguageService()->getLL('edit', TRUE) . '">'
+                                                       . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>'
+                                                       : ''
+                                               ) . htmlspecialchars(GeneralUtility::fixed_lgd_cs($this->pageRecord['title'], 20));
                                }
+                               $sCont[$lP] = '
+                                       <td nowrap="nowrap" class="t3-page-column t3-page-lang-label">' . $lPLabel . '</td>';
                        }
-                       if ($this->ext_CALC_PERMS & 4 || $this->ext_CALC_PERMS & 2) {
-                               $bArray[1] = $this->getPageLayoutController()->doc->t3Button(
-                                       'window.location.href=\'' . $this->backPath . 'move_el.php?table=pages&uid=' . $id
-                                               . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';',
-                                       $this->getLanguageService()->getLL('move_page')
-                               );
-                       }
-                       if ($this->ext_CALC_PERMS & 8) {
-                               $bArray[2] = $this->getPageLayoutController()->doc->t3Button(
-                                       'window.location.href=\'' . $this->backPath . 'db_new.php?id=' . $id
-                                               . '&pagesOnly=1&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';',
-                                       $this->getLanguageService()->getLL('newPage2')
-                               );
-                       }
-                       if ($this->doEdit && $this->ext_function == 1) {
-                               $bArray[3] = $this->getPageLayoutController()->doc->t3Button(
-                                       'window.location.href=\'db_new_content_el.php?id=' . $id
-                                               . '&sys_language_uid=' . $this->getPageLayoutController()->current_sys_language
-                                               . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';',
-                                       $this->getLanguageService()->getLL('newPageContent2')
-                               );
+                       // Add headers:
+                       $out .= '<tr>' . implode($cCont) . '</tr>';
+                       $out .= '<tr>' . implode($sCont) . '</tr>';
+                       unset($cCont, $sCont);
+
+                       // Traverse previously built content for the columns:
+                       foreach ($languageColumn as $cKey => $cCont) {
+                               $out .= '<tr>';
+                               foreach ($cCont as $languageId => $columnContent) {
+                                       $out .= '<td valign="top" class="t3-grid-cell t3-page-column t3js-page-column t3js-page-lang-column t3js-page-lang-column-' . $languageId . '">' . $columnContent . '</td>';
+                               }
+                               $out .= '</tr>';
+                               if ($this->defLangBinding) {
+                                       // "defLangBinding" mode
+                                       foreach ($defLanguageCount[$cKey] as $defUid) {
+                                               $cCont = array();
+                                               foreach ($langListArr as $lP) {
+                                                       $cCont[] = $defLangBinding[$cKey][$lP][$defUid] . $this->newLanguageButton(
+                                                               $this->getNonTranslatedTTcontentUids(array($defUid), $id, $lP),
+                                                               $lP,
+                                                               $cKey
+                                                       );
+                                               }
+                                               $out .= '
+                                               <tr>
+                                                       <td valign="top" class="t3-grid-cell">' . implode(('</td>' . '
+                                                       <td valign="top" class="t3-grid-cell">'), $cCont) . '</td>
+                                               </tr>';
+                                       }
+                               }
                        }
-                       $out = '
-                               <table border="0" cellpadding="4" cellspacing="0" class="typo3-page-buttons">
-                                       <tr>
-                                               <td>' . implode('</td>
-                                               <td>', $bArray) . '</td>
-                                               <td>' . BackendUtility::cshItem($this->descrTable, 'button_panel', $GLOBALS['BACK_PATH']) . '</td>
-                                       </tr>
-                               </table>
-                               <br />
-                               ' . $out;
-               }
-               // Return content:
-               return $out;
-       }
+                       // Finally, wrap it all in a table and add the language selector on top of it:
+                       $out = $languageSelector . '
+                               <div class="t3-grid-container">
+                                       <table cellpadding="0" cellspacing="0" class="t3-page-columns t3-grid-table t3js-page-columns">
+                                               ' . $out . '
+                                       </table>
+                               </div>';
+                       // CSH:
+                       $out .= BackendUtility::cshItem($this->descrTable, 'language_list');
+               }
 
-       /**
-        * Get backend layout configuration
-        *
-        * @return array
-        * @deprecated since TYPO3 CMS 6.2, will be removed two versions later
-        */
-       public function getBackendLayoutConfiguration() {
-               GeneralUtility::logDeprecatedFunction();
-               return $this->getBackendLayoutView()->getSelectedBackendLayout($this->id);
+               return $out;
        }
 
        /**********************************
@@ -959,19 +828,18 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                $theData = $this->headerFields($this->fieldArray, $table, $theData);
                // Title row
                $localizedTableTitle = $this->getLanguageService()->sL($GLOBALS['TCA'][$table]['ctrl']['title'], TRUE);
-               $out .= '<tr class="t3-row-header">' . '<td nowrap="nowrap" class="col-icon"></td>'
-                       . '<td nowrap="nowrap" colspan="' . (count($theData) - 2) . '"><span class="c-table">'
-                       . $localizedTableTitle . '</span> (' . $dbCount . ')</td>' . '<td nowrap="nowrap" class="col-icon"></td>'
+               $out .= '<tr class="t3-row-header">' . '<th class="col-icon"></th>'
+                       . '<th colspan="' . (count($theData) - 2) . '"><span class="c-table">'
+                       . $localizedTableTitle . '</span> (' . $dbCount . ')</td>' . '<td class="col-icon"></td>'
                        . '</tr>';
                // Column's titles
                if ($this->doEdit) {
-                       $theData['__cmds__'] = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick(
-                                       '&edit[' . $table . '][' . $this->id . ']=new',
-                                       $this->backPath
-                               )) . '" title="' . $this->getLanguageService()->getLL('new', TRUE) . '">'
-                               . IconUtility::getSpriteIcon('actions-document-new') . '</a>';
+                       $onClick = BackendUtility::editOnClick('&edit[' . $table . '][' . $this->id . ']=new');
+                       $theData['__cmds__'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" '
+                               . 'title="' . $this->getLanguageService()->getLL('new', TRUE) . '">'
+                               . $this->iconFactory->getIcon('actions-document-new', Icon::SIZE_SMALL)->render() . '</a>';
                }
-               $out .= $this->addelement(1, '', $theData, ' class="c-headLine"', 15);
+               $out .= $this->addelement(1, '', $theData, ' class="c-headLine"', 15, '', 'th');
                // Render Items
                $this->eCounter = $this->firstElementNumber;
                while ($row = $this->getDatabase()->sql_fetch_assoc($result)) {
@@ -990,26 +858,26 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                        $Nrow = $this->dataFields($this->fieldArray, $table, $row, $Nrow);
                                        // Attach edit icon
                                        if ($this->doEdit) {
-                                               $Nrow['__editIconLink__'] = '<a href="#" onclick="' . htmlspecialchars(
-                                                               BackendUtility::editOnClick($params, $this->backPath))
+                                               $Nrow['__editIconLink__'] = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params))
                                                        . '" title="' . $this->getLanguageService()->getLL('edit', TRUE) . '">'
-                                                       . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
+                                                       . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
                                        } else {
                                                $Nrow['__editIconLink__'] = $this->noEditIcon();
                                        }
-                                       $out .= $this->addelement(1, '', $Nrow, 'class="db_list_normal"');
+                                       $out .= $this->addelement(1, '', $Nrow);
                                }
                                $this->eCounter++;
                        }
                }
+               $this->getDatabase()->sql_free_result($result);
                // Wrap it all in a table:
                $out = '
                        <!--
                                Standard list of table "' . $table . '"
                        -->
-                       <table border="0" cellpadding="0" cellspacing="0" class="typo3-dblist">
+                       <div class="table-fit"><table class="table table-striped">
                                ' . $out . '
-                       </table>';
+                       </table></div>';
                return $out;
        }
 
@@ -1071,7 +939,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        }
                        // Wrap in dimmed-span tags if record is "disabled"
                        if ($this->isDisabled($table, $row)) {
-                               $out[$fieldName] = $this->getDocumentTemplate()->dfw($out[$fieldName]);
+                               $out[$fieldName] = '<span class="text-muted">' . $out[$fieldName] . '</span>';
                        }
                }
                return $out;
@@ -1146,18 +1014,10 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                BackendUtility::workspaceOL('pages', $row);
                                if (is_array($row)) {
                                        $c++;
-                                       $row['treeIcons'] = $treeIcons . '<img' . IconUtility::skinImg(
-                                                       $this->backPath,
-                                                       'gfx/ol/join' . ($rc == $c ? 'bottom' : '') . '.gif',
-                                                       'width="18" height="16"'
-                                               ) . ' alt="" />';
+                                       $row['treeIcons'] = $treeIcons . '<span class="treeline-icon treeline-icon-join' . ($rc === $c ? 'bottom' : '') . '"></span>';
                                        $theRows[] = $row;
                                        // Get the branch
-                                       $spaceOutIcons = '<img' . IconUtility::skinImg(
-                                                       $this->backPath,
-                                                       'gfx/ol/' . ($rc == $c ? 'blank.gif' : 'line.gif'),
-                                                       'width="18" height="16"'
-                                               ) . ' alt="" />';
+                                       $spaceOutIcons = '<span class="treeline-icon treeline-icon-' . ($rc === $c ? 'clear' : 'line') . '"></span>';
                                        $theRows = $this->pages_getTree($theRows, $row['uid'], $qWhere, $treeIcons . $spaceOutIcons, $row['php_tree_stop'] ? 0 : $depth);
                                }
                        }
@@ -1185,7 +1045,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                foreach ($fieldArr as $field) {
                        switch ($field) {
                                case 'title':
-                                       $red = $this->plusPages[$row['uid']] ? '<font color="red"><strong>+&nbsp;</strong></font>' : '';
+                                       $red = $this->plusPages[$row['uid']] ? '<span class="text-danger"><strong>+</strong></span>' : '';
                                        $pTitle = htmlspecialchars(BackendUtility::getProcessedValue('pages', $field, $row[$field], 20));
                                        if ($red) {
                                                $pTitle = '<a href="'
@@ -1203,14 +1063,20 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                        if ($this->getBackendUser()->doesUserHaveAccess($row, 2)) {
                                                $params = '&edit[pages][' . $row['uid'] . ']=edit';
                                                $eI = '<a href="#" onclick="'
-                                                       . htmlspecialchars(BackendUtility::editOnClick($params, $this->backPath, ''))
+                                                       . htmlspecialchars(BackendUtility::editOnClick($params))
                                                        . '" title="' . $this->getLanguageService()->getLL('editThisPage', TRUE) . '">'
-                                                       . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
+                                                       . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
                                        } else {
                                                $eI = '';
                                        }
                                        $theData[$field] = '<span align="right">' . $row['uid'] . $eI . '</span>';
                                        break;
+                               case 'shortcut':
+                               case 'shortcut_mode':
+                                       if ((int)$row['doktype'] === \TYPO3\CMS\Frontend\Page\PageRepository::DOKTYPE_SHORTCUT) {
+                                               $theData[$field] = $this->getPagesTableFieldValue($field, $row);
+                                       }
+                                       break;
                                default:
                                        if (substr($field, 0, 6) == 'table_') {
                                                $f2 = substr($field, 6);
@@ -1219,8 +1085,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                        $theData[$field] = '&nbsp;&nbsp;' . ($c ? $c : '');
                                                }
                                        } else {
-                                               $theData[$field] = '&nbsp;&nbsp;'
-                                                       . htmlspecialchars(BackendUtility::getProcessedValue('pages', $field, $row[$field]));
+                                               $theData[$field] = $this->getPagesTableFieldValue($field, $row);
                                        }
                        }
                }
@@ -1228,6 +1093,18 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                return $this->addelement(1, '', $theData);
        }
 
+       /**
+        * Returns the HTML code for rendering a field in the pages table.
+        * The row value is processed to a human readable form and the result is parsed through htmlspecialchars().
+        *
+        * @param string $field The name of the field of which the value should be rendered.
+        * @param array $row The pages table row as an associative array.
+        * @return string The rendered table field value.
+        */
+       protected function getPagesTableFieldValue($field, array $row) {
+               return '&nbsp;&nbsp;' . htmlspecialchars(BackendUtility::getProcessedValue('pages', $field, $row[$field]));
+       }
+
        /**********************************
         *
         * Additional functions; Content Elements
@@ -1237,8 +1114,8 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         * Draw header for a content element column:
         *
         * @param string $colName Column name
-        * @param string $editParams Edit params (Syntax: &edit[...] for alt_doc.php)
-        * @param string $newParams New element params (Syntax: &edit[...] for alt_doc.php) OBSOLETE
+        * @param string $editParams Edit params (Syntax: &edit[...] for FormEngine)
+        * @param string $newParams New element params (Syntax: &edit[...] for FormEngine) OBSOLETE
         * @param array|NULL $pasteParams Paste element params (i.e. array(colPos => 1, sys_language_uid => 2))
         * @return string HTML table
         */
@@ -1249,30 +1126,30 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        // Edit whole of column:
                        if ($editParams) {
                                $iconsArr['edit'] = '<a href="#" onclick="'
-                                       . htmlspecialchars(BackendUtility::editOnClick($editParams, $this->backPath)) . '" title="'
+                                       . htmlspecialchars(BackendUtility::editOnClick($editParams)) . '" title="'
                                        . $this->getLanguageService()->getLL('editColumn', TRUE) . '">'
-                                       . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
+                                       . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
                        }
                        if ($pasteParams) {
                                $elFromTable = $this->clipboard->elFromTable('tt_content');
-                               if (count($elFromTable)) {
+                               if (!empty($elFromTable) && $this->getPageLayoutController()->pageIsNotLockedForEditors()) {
                                        $iconsArr['paste'] = '<a href="'
                                                . htmlspecialchars($this->clipboard->pasteUrl('tt_content', $this->id, TRUE, $pasteParams))
                                                . '" onclick="' . htmlspecialchars(('return '
                                                . $this->clipboard->confirmMsg('pages', $this->pageRecord, 'into', $elFromTable, $colName)))
-                                               . '" title="' . $this->getLanguageService()->getLL('clip_paste', TRUE) . '">'
-                                               . IconUtility::getSpriteIcon('actions-document-paste-into') . '</a>';
+                                               . '" title="' . $this->getLanguageService()->getLL('pasteIntoColumn', TRUE) . '">'
+                                               . $this->iconFactory->getIcon('actions-document-paste-into', Icon::SIZE_SMALL)->render() . '</a>';
                                }
                        }
                }
                $icons = '';
-               if (count($iconsArr)) {
-                       $icons = '<div class="t3-page-colHeader-icons">' . implode('', $iconsArr) . '</div>';
+               if (!empty($iconsArr)) {
+                       $icons = '<div class="t3-page-column-header-icons">' . implode('', $iconsArr) . '</div>';
                }
                // Create header row:
-               $out = '<div class="t3-page-colHeader t3-row-header">
+               $out = '<div class="t3-page-column-header">
                                        ' . $icons . '
-                                       <div class="t3-page-colHeader-label">' . htmlspecialchars($colName) . '</div>
+                                       <div class="t3-page-column-header-label">' . htmlspecialchars($colName) . '</div>
                                </div>';
                return $out;
        }
@@ -1282,16 +1159,35 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         *
         * @param array $row Record array
         * @return string HTML of the footer
+        * @throws \UnexpectedValueException
         */
        protected function tt_content_drawFooter(array $row) {
                $content = '';
                // Get processed values:
                $info = array();
                $this->getProcessedValue('tt_content', 'starttime,endtime,fe_group,spaceBefore,spaceAfter', $row, $info);
+
+               // Content element annotation
+               if (!empty($GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn'])) {
+                       $info[] = htmlspecialchars($row[$GLOBALS['TCA']['tt_content']['ctrl']['descriptionColumn']]);
+               }
+
+                       // Call drawFooter hooks
+               $drawFooterHooks = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawFooter'];
+               if (is_array($drawFooterHooks)) {
+                       foreach ($drawFooterHooks as $hookClass) {
+                               $hookObject = GeneralUtility::getUserObj($hookClass);
+                               if (!$hookObject instanceof PageLayoutViewDrawFooterHookInterface) {
+                                       throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\View\\PageLayoutViewDrawFooterHookInterface', 1404378171);
+                               }
+                               $hookObject->preProcess($this, $info, $row);
+                       }
+               }
+
                // Display info from records fields:
-               if (count($info)) {
+               if (!empty($info)) {
                        $content = '<div class="t3-page-ce-info">
-                               ' . implode('<br />', $info) . '
+                               ' . implode('<br>', $info) . '
                                </div>';
                }
                // Wrap it
@@ -1319,14 +1215,14 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        if ($this->tt_contentConfig['showCommands'] && $this->doEdit) {
                                // Edit content element:
                                $params = '&edit[tt_content][' . $this->tt_contentData['nextThree'][$row['uid']] . ']=edit';
-                               $out .= '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick(
+                               $out .= '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick(
                                                $params,
-                                               $this->backPath,
+                                               '',
                                                GeneralUtility::getIndpEnv('REQUEST_URI') . '#element-tt_content-' . $row['uid']
                                        )) . '" title="' . htmlspecialchars($this->nextThree > 1
                                                ? sprintf($this->getLanguageService()->getLL('nextThree'), $this->nextThree)
                                                : $this->getLanguageService()->getLL('edit'))
-                                       . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
+                                       . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render() . '</a>';
                                // Hide element:
                                $hiddenField = $GLOBALS['TCA']['tt_content']['ctrl']['enablecolumns']['disabled'];
                                if (
@@ -1343,51 +1239,57 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                        }
                                        $params = '&data[tt_content][' . ($row['_ORIG_uid'] ? $row['_ORIG_uid'] : $row['uid'])
                                                . '][' . $hiddenField . ']=' . $value;
-                                       $out .= '<a href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params))
+                                       $out .= '<a class="btn btn-default" href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params))
                                                . '" title="' . $this->getLanguageService()->getLL($label, TRUE) . '">'
-                                               . IconUtility::getSpriteIcon('actions-edit-' . strtolower($label)) . '</a>';
+                                               . $this->iconFactory->getIcon('actions-edit-' . strtolower($label), Icon::SIZE_SMALL)->render() . '</a>';
                                }
                                // Delete
                                $params = '&cmd[tt_content][' . $row['uid'] . '][delete]=1';
-                               $confirm = GeneralUtility::quoteJSvalue($this->getLanguageService()->getLL('deleteWarning')
+                               $confirm = $this->getLanguageService()->getLL('deleteWarning')
                                        . BackendUtility::translationCount('tt_content', $row['uid'], (' '
-                                               . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord')))
+                                       . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.translationsOfRecord'))
                                );
-                               $out .= '<a href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params))
-                                       . '" onclick="' . htmlspecialchars(('return confirm(' . $confirm . ');')) . '" title="'
-                                       . $this->getLanguageService()->getLL('deleteItem', TRUE) . '">'
-                                       . IconUtility::getSpriteIcon('actions-edit-delete') . '</a>';
+                               $out .= '<a class="btn btn-default t3js-modal-trigger" href="' . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params)) . '"'
+                                       . ' data-severity="warning"'
+                                       . ' data-title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_alt_doc.xlf:label.confirm.delete_record.title')) . '"'
+                                       . ' data-content="' . htmlspecialchars($confirm) . '" '
+                                       . ' data-button-close-text="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:cancel')) . '"'
+                                       . ' title="' . $this->getLanguageService()->getLL('deleteItem', TRUE) . '">'
+                                       . $this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL)->render() . '</a>';
+                               if ($out) {
+                                       $out = '<div class="btn-group btn-group-sm" role="group">' . $out . '</div>';
+                               }
                                if (!$disableMoveAndNewButtons) {
                                        $moveButtonContent = '';
                                        $displayMoveButtons = FALSE;
                                        // Move element up:
                                        if ($this->tt_contentData['prev'][$row['uid']]) {
                                                $params = '&cmd[tt_content][' . $row['uid'] . '][move]=' . $this->tt_contentData['prev'][$row['uid']];
-                                               $moveButtonContent .= '<a href="'
+                                               $moveButtonContent .= '<a class="btn btn-default" href="'
                                                        . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params))
                                                        . '" title="' . $this->getLanguageService()->getLL('moveUp', TRUE) . '">'
-                                                       . IconUtility::getSpriteIcon('actions-move-up') . '</a>';
+                                                       . $this->iconFactory->getIcon('actions-move-up', Icon::SIZE_SMALL)->render() . '</a>';
                                                if (!$dragDropEnabled) {
                                                        $displayMoveButtons = TRUE;
                                                }
                                        } else {
-                                               $moveButtonContent .= IconUtility::getSpriteIcon('empty-empty');
+                                               $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>';
                                        }
                                        // Move element down:
                                        if ($this->tt_contentData['next'][$row['uid']]) {
                                                $params = '&cmd[tt_content][' . $row['uid'] . '][move]= ' . $this->tt_contentData['next'][$row['uid']];
-                                               $moveButtonContent .= '<a href="'
+                                               $moveButtonContent .= '<a class="btn btn-default" href="'
                                                        . htmlspecialchars($this->getPageLayoutController()->doc->issueCommand($params))
                                                        . '" title="' . $this->getLanguageService()->getLL('moveDown', TRUE) . '">'
-                                                       . IconUtility::getSpriteIcon('actions-move-down') . '</a>';
+                                                       . $this->iconFactory->getIcon('actions-move-down', Icon::SIZE_SMALL)->render() . '</a>';
                                                if (!$dragDropEnabled) {
                                                        $displayMoveButtons = TRUE;
                                                }
                                        } else {
-                                               $moveButtonContent .= IconUtility::getSpriteIcon('empty-empty');
+                                               $moveButtonContent .= '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>';
                                        }
                                        if ($displayMoveButtons) {
-                                               $out .= '<span class="t3-page-ce-icons-move">' . $moveButtonContent . '</span>';
+                                               $out .= '<div class="btn-group btn-group-sm" role="group">' . $moveButtonContent . '</div>';
                                        }
                                }
                        }
@@ -1399,7 +1301,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) {
                        $additionalIcons[] = '<a href="#" onclick="alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg'])
                                . ');return false;" title="' . htmlspecialchars($lockInfo['msg']) . '">'
-                               . IconUtility::getSpriteIcon('status-warning-in-use') . '</a>';
+                               . $this->iconFactory->getIcon('status-warning-in-use', Icon::SIZE_SMALL)->render() . '</a>';
                }
                // Call stats information hook
                if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'])) {
@@ -1410,28 +1312,25 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                }
                // Wrap the whole header
                // NOTE: end-tag for <div class="t3-page-ce-body"> is in getTable_tt_content()
-               return '<h4 class="t3-page-ce-header">
-                                       <div class="t3-row-header">
-                                       <span class="ce-icons-left">' . implode('', $additionalIcons) . '</span>
-                                       <span class="ce-icons">
-                                       ' . $out . '
-                                       </span></div>
-                               </h4>
+               return '<div class="t3-page-ce-header ' . ($this->getBackendUser()->user['admin'] || ((int)$row['editlock'] === 0 && (int)$this->pageinfo['editlock'] === 0)  ? 't3-page-ce-header-draggable t3js-page-ce-draghandle' : '') . '">
+                                       <div class="t3-page-ce-header-icons-left">' . implode('', $additionalIcons) . '</div>
+                                       <div class="t3-page-ce-header-icons-right">' . ($out ? '<div class="btn-toolbar">' .$out . '</div>' : '') . '</div>
+                               </div>
                                <div class="t3-page-ce-body">';
        }
 
        /**
         * Draws the preview content for a content element
         *
-        * @param string $row Content element
-        * @param bool $isRTE Set if the RTE link can be created.
+        * @param array $row Content element
         * @return string HTML
         * @throws \UnexpectedValueException
         */
-       public function tt_content_drawItem($row, $isRTE = FALSE) {
+       public function tt_content_drawItem($row) {
                $out = '';
                $outHeader = '';
                // Make header:
+
                if ($row['header']) {
                        $infoArr = array();
                        $this->getProcessedValue('tt_content', 'header_position,header_layout,header_link', $row, $infoArr);
@@ -1455,11 +1354,41 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        foreach ($drawItemHooks as $hookClass) {
                                $hookObject = GeneralUtility::getUserObj($hookClass);
                                if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) {
-                                       throw new \UnexpectedValueException('$hookObject must implement interface TYPO3\\CMS\\Backend\\View\\PageLayoutViewDrawItemHookInterface', 1218547409);
+                                       throw new \UnexpectedValueException('$hookObject must implement interface ' . \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface::class, 1218547409);
                                }
                                $hookObject->preProcess($this, $drawItem, $outHeader, $out, $row);
                        }
                }
+
+               // If the previous hook did not render something,
+               // then check if a Fluid-based preview template was defined for this CType
+               // and render it via Fluid. Possible option:
+               // mod.web_layout.tt_content.preview.media = EXT:site_mysite/Resources/Private/Templates/Preview/Media.html
+               if ($drawItem) {
+                       $tsConfig = BackendUtility::getModTSconfig($row['pid'], 'mod.web_layout.tt_content.preview');
+                       if (!empty($tsConfig['properties'][$row['CType']])) {
+                               $fluidTemplateFile = $tsConfig['properties'][$row['CType']];
+                               $fluidTemplateFile = GeneralUtility::getFileAbsFileName($fluidTemplateFile);
+                               if ($fluidTemplateFile) {
+                                       try {
+                                               /** @var StandaloneView $view */
+                                               $view = GeneralUtility::makeInstance(StandaloneView::class);
+                                               $view->setTemplatePathAndFilename($fluidTemplateFile);
+                                               $view->assignMultiple($row);
+                                               if (!empty($row['pi_flexform'])) {
+                                                       /** @var FlexFormService $flexFormService */
+                                                       $flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
+                                                       $view->assign('pi_flexform_transformed', $flexFormService->convertFlexFormContentToArray($row['pi_flexform']));
+                                               }
+                                               $out = $view->render();
+                                               $drawItem = FALSE;
+                                       } catch (\Exception $e) {
+                                               // Catch any exception to avoid breaking the view
+                                       }
+                               }
+                       }
+               }
+
                // Draw preview of the item depending on its CType (if not disabled by previous hook):
                if ($drawItem) {
                        switch ($row['CType']) {
@@ -1468,48 +1397,29 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                $out .= $this->linkEditContent($this->renderText($row['subheader']), $row) . '<br />';
                                        }
                                        break;
-                               case 'text':
-
-                               case 'textpic':
-
-                               case 'image':
-                                       if ($row['CType'] == 'text' || $row['CType'] == 'textpic') {
-                                               if ($row['bodytext']) {
-                                                       $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />';
-                                               }
-                                       }
-                                       if ($row['CType'] == 'textpic' || $row['CType'] == 'image') {
-                                               if ($row['image']) {
-                                                       $out .= $this->thumbCode($row, 'tt_content', 'image') . '<br />';
-                                                       if ($row['imagecaption']) {
-                                                               $out .= $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '<br />';
-                                                       }
-                                               }
-                                       }
-                                       break;
                                case 'bullets':
-
                                case 'table':
-
-                               case 'mailform':
                                        if ($row['bodytext']) {
                                                $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />';
                                        }
                                        break;
                                case 'uploads':
                                        if ($row['media']) {
-                                               $out .= $this->thumbCode($row, 'tt_content', 'media') . '<br />';
-                                       }
-                                       break;
-                               case 'multimedia':
-                                       if ($row['multimedia']) {
-                                               $out .= $this->renderText($row['multimedia']) . '<br />';
-                                               $out .= $this->renderText($row['parameters']) . '<br />';
+                                               $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'media'), $row) . '<br />';
                                        }
                                        break;
                                case 'menu':
-                                       if ($row['pages']) {
-                                               $out .= $this->linkEditContent($row['pages'], $row) . '<br />';
+                                       $contentType = $this->CType_labels[$row['CType']];
+                                       $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />';
+                                       // Add Menu Type
+                                       $menuTypeLabel = $this->getLanguageService()->sL(
+                                               BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'menu_type', $row['menu_type'])
+                                       );
+                                       $menuTypeLabel = $menuTypeLabel ?: 'invalid menu type';
+                                       $out .= $this->linkEditContent($menuTypeLabel, $row);
+                                       if ($row['menu_type'] !== '2' && ($row['pages'] || $row['selected_categories'])) {
+                                               // Show pages if menu type is not "Sitemap"
+                                               $out .= ':' . $this->linkEditContent($this->generateListForCTypeMenu($row), $row) . '<br />';
                                        }
                                        break;
                                case 'shortcut':
@@ -1521,10 +1431,10 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                        $tableName = empty($split[0]) ? 'tt_content' : $split[0];
                                                        $shortcutRecord = BackendUtility::getRecord($tableName, $split[1]);
                                                        if (is_array($shortcutRecord)) {
-                                                               $icon = IconUtility::getSpriteIconForRecord($tableName, $shortcutRecord);
-                                                               $onClick = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon($icon, $tableName,
-                                                                       $shortcutRecord['uid'], 1, '', '+copy,info,edit,view', TRUE);
-                                                               $shortcutContent[] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $icon . '</a>'
+                                                               $icon = $this->iconFactory->getIconForRecord($tableName, $shortcutRecord, Icon::SIZE_SMALL)->render();
+                                                               $icon = $this->getPageLayoutController()->doc->wrapClickMenuOnIcon($icon, $tableName,
+                                                                       $shortcutRecord['uid'], 1, '', '+copy,info,edit,view');
+                                                               $shortcutContent[] = $icon
                                                                        . htmlspecialchars(BackendUtility::getRecordTitle($tableName, $shortcutRecord));
                                                        }
                                                }
@@ -1539,7 +1449,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                        } elseif (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'])) {
                                                $hookArr = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info']['_DEFAULT'];
                                        }
-                                       if (count($hookArr) > 0) {
+                                       if (!empty($hookArr)) {
                                                $_params = array('pObj' => &$this, 'row' => $row, 'infoArr' => $infoArr);
                                                foreach ($hookArr as $_funcRef) {
                                                        $hookOut .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
@@ -1548,13 +1458,13 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                        if ((string)$hookOut !== '') {
                                                $out .= $hookOut;
                                        } elseif (!empty($row['list_type'])) {
-                                               $label = BackendUtility::getLabelFromItemlist('tt_content', 'list_type', $row['list_type']);
+                                               $label = BackendUtility::getLabelFromItemListMerged($row['pid'], 'tt_content', 'list_type', $row['list_type']);
                                                if (!empty($label)) {
-                                                       $out .=  '<strong>' . $this->getLanguageService()->sL($label, TRUE) . '</strong><br />';
+                                                       $out .=  $this->linkEditContent('<strong>' . $this->getLanguageService()->sL($label, TRUE) . '</strong>', $row) . '<br />';
                                                } else {
                                                        $message = sprintf($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue'), $row['list_type']);
                                                        $out .= GeneralUtility::makeInstance(
-                                                               'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                                                               FlashMessage::class,
                                                                htmlspecialchars($message),
                                                                '',
                                                                FlashMessage::WARNING
@@ -1571,22 +1481,16 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                        TRUE
                                                ) . '<br />';
                                        break;
-                               case 'script':
-                                       $out .= $this->getLanguageService()->sL(BackendUtility::getItemLabel('tt_content', 'select_key'), TRUE)
-                                               . ' ' . $row['select_key'] . '<br />';
-                                       $out .= '<br />' . $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />';
-                                       $out .= '<br />' . $this->linkEditContent($this->renderText($row['imagecaption']), $row) . '<br />';
-                                       break;
                                default:
                                        $contentType = $this->CType_labels[$row['CType']];
 
                                        if (isset($contentType)) {
-                                               $out .= '<strong>' . htmlspecialchars($contentType) . '</strong><br />';
+                                               $out .= $this->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />';
                                                if ($row['bodytext']) {
                                                        $out .= $this->linkEditContent($this->renderText($row['bodytext']), $row) . '<br />';
                                                }
                                                if ($row['image']) {
-                                                       $out .= $this->thumbCode($row, 'tt_content', 'image') . '<br />';
+                                                       $out .= $this->linkEditContent($this->getThumbCodeUnlinked($row, 'tt_content', 'image'), $row) . '<br />';
                                                }
                                        } else {
                                                $message = sprintf(
@@ -1594,7 +1498,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                                        $row['CType']
                                                );
                                                $out .= GeneralUtility::makeInstance(
-                                                       'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
+                                                       FlashMessage::class,
                                                        htmlspecialchars($message),
                                                        '',
                                                        FlashMessage::WARNING
@@ -1607,19 +1511,42 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        <span class="exampleContent">' . $out . '</span>';
                // Add header:
                $out = $outHeader . $out;
-               // Add RTE button:
-               if ($isRTE) {
-                       $out .= $this->linkRTEbutton($row);
-               }
                // Return values:
                if ($this->isDisabled('tt_content', $row)) {
-                       return $this->getDocumentTemplate()->dfw($out);
+                       return '<span class="text-muted">' . $out . '</span>';
                } else {
                        return $out;
                }
        }
 
        /**
+        * Generates a list of selected pages or categories for the CType menu
+        *
+        * @param array $row row from pages
+        * @return string
+        */
+       protected function generateListForCTypeMenu(array $row) {
+               $table = 'pages';
+               $field = 'pages';
+               // get categories instead of pages
+               if (strpos($row['menu_type'], 'categorized_') !== FALSE) {
+                       $table = 'sys_category';
+                       $field = 'selected_categories';
+               }
+               if (trim($row[$field]) === '') {
+                       return '';
+               }
+               $content = '';
+               $uidList = explode(',', $row[$field]);
+               foreach ($uidList as $uid) {
+                       $uid = (int)$uid;
+                       $record = BackendUtility::getRecord($table, $uid, 'title');
+                       $content .= '<br>' . $record['title'] . ' (' .$uid. ')';
+               }
+               return $content;
+       }
+
+       /**
         * Filters out all tt_content uids which are already translated so only non-translated uids is left.
         * Selects across columns, but within in the same PID. Columns are expect to be the same
         * for translations and original but this may be a conceptual error (?)
@@ -1630,16 +1557,18 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         * @return array Modified $defLanguageCount
         */
        public function getNonTranslatedTTcontentUids($defLanguageCount, $id, $lP) {
-               if ($lP && count($defLanguageCount)) {
+               if ($lP && !empty($defLanguageCount)) {
                        // Select all translations here:
-                       $queryParts = $this->makeQueryArray('tt_content', $id, 'AND sys_language_uid=' . (int)$lP
-                               . ' AND l18n_parent IN (' . implode(',', $defLanguageCount) . ')');
-                       $result = $this->getDatabase()->exec_SELECT_queryArray($queryParts);
+                       $where = 'sys_language_uid=' . intval($lP) . ' AND l18n_parent IN ('
+                               . implode(',', $defLanguageCount) . ')'
+                               . BackendUtility::deleteClause('tt_content');
+                       $rowArr = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'tt_content', $where);
+
                        // Flip uids:
                        $defLanguageCount = array_flip($defLanguageCount);
                        // Traverse any selected elements and unset original UID if any:
-                       $rowArr = $this->getResult($result);
                        foreach ($rowArr as $row) {
+                               BackendUtility::workspaceOL('tt_content', $row);
                                unset($defLanguageCount[$row['l18n_parent']]);
                        }
                        // Flip again:
@@ -1653,24 +1582,66 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         *
         * @param array $defLanguageCount Numeric array with uids of tt_content elements in the default language
         * @param int $lP Sys language UID
+        * @param int $colPos Column position
         * @return string "Copy languages" button, if available.
         */
-       public function newLanguageButton($defLanguageCount, $lP) {
-               if (!$this->doEdit || count($defLanguageCount) === 0 || !$lP) {
+       public function newLanguageButton($defLanguageCount, $lP, $colPos = 0) {
+               if (!$this->doEdit || !$lP) {
                        return '';
                }
-               $params = '';
-               foreach ($defLanguageCount as $uidVal) {
-                       $params .= '&cmd[tt_content][' . $uidVal . '][localize]=' . $lP;
-               }
-               // Copy for language:
-               $onClick = 'window.location.href=\'' . $this->getPageLayoutController()->doc->issueCommand($params) . '\'; return false;';
-               $theNewButton = '<div class="t3-page-lang-copyce">' .
-                       $this->getPageLayoutController()->doc->t3Button(
-                               $onClick,
-                               $this->getLanguageService()->getLL('newPageContent_copyForLang') . ' [' . count($defLanguageCount) . ']'
-                       ) . '</div>';
-               return $theNewButton;
+
+               $copyFromLanguageMenu = '';
+               foreach ($this->getLanguagesToCopyFrom(GeneralUtility::_GP('id'), $lP, $colPos) as $languageId => $label) {
+                       $elementsInColumn = $languageId === 0 ? $defLanguageCount : $this->getElementsFromColumnAndLanguage(GeneralUtility::_GP('id'), $colPos, $languageId);
+                       if (!empty($elementsInColumn)) {
+                               $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue($this->getPageLayoutController()->doc->issueCommand('&cmd[tt_content][' . implode(',', $elementsInColumn) . '][copyFromLanguage]=' . GeneralUtility::_GP('id') . ',' . $lP)) . '; return false;';
+                               $copyFromLanguageMenu .= '<li><a href="#" onclick="' . htmlspecialchars($onClick) . '">' . $this->languageFlag($languageId, FALSE) . ' ' . htmlspecialchars($label) . '</a></li>' . LF;
+                       }
+               }
+               if ($copyFromLanguageMenu !== '') {
+                       $copyFromLanguageMenu =
+                               '<ul class="dropdown-menu">'
+                                       . $copyFromLanguageMenu
+                               . '</ul>';
+               }
+
+               if (!empty($defLanguageCount)) {
+                       $params = '';
+                       foreach ($defLanguageCount as $uidVal) {
+                               $params .= '&cmd[tt_content][' . $uidVal . '][localize]=' . $lP;
+                       }
+
+                       // We have content in the default language, create a split button
+                       $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue($this->getPageLayoutController()->doc->issueCommand($params)) . '; return false;';
+                       $theNewButton =
+                               '<div class="btn-group">'
+                                       . $this->getPageLayoutController()->doc->t3Button(
+                                               $onClick,
+                                               $this->getLanguageService()->getLL('newPageContent_copyForLang', TRUE) . ' [' . count($defLanguageCount) . ']'
+                                       );
+                       if ($copyFromLanguageMenu !== '' && $this->isColumnEmpty($colPos, $lP)) {
+                               $theNewButton .= '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'
+                                       . '<span class="caret"></span>'
+                                       . '<span class="sr-only">Toggle Dropdown</span>'
+                                       . '</button>'
+                                       . $copyFromLanguageMenu;
+                       }
+                       $theNewButton .= '</div>';
+               } else {
+                       if ($copyFromLanguageMenu !== '' && $this->isColumnEmpty($colPos, $lP)) {
+                               $theNewButton =
+                                       '<div class="btn-group">'
+                                       . '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">'
+                                       . $this->getLanguageService()->getLL('newPageContent_copyFromAnotherLang_button', TRUE) . ' <span class="caret"></span>'
+                                       . '</button>'
+                                       . $copyFromLanguageMenu
+                                       . '</div>';
+                       } else {
+                               $theNewButton = '';
+                       }
+               }
+
+               return '<div class="t3-page-lang-copyce">' . $theNewButton . '</div>';
        }
 
        /**
@@ -1684,12 +1655,12 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         */
        public function newContentElementOnClick($id, $colPos, $sys_language) {
                if ($this->option_newWizard) {
-                       $onClick = 'window.location.href=\'db_new_content_el.php?id=' . $id . '&colPos=' . $colPos
+                       $onClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('new_content_element') . '&id=' . $id . '&colPos=' . $colPos
                                . '&sys_language_uid=' . $sys_language . '&uid_pid=' . $id
-                               . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\';';
+                               . '&returnUrl=' . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI'))) . ';';
                } else {
                        $onClick = BackendUtility::editOnClick('&edit[tt_content][' . $id . ']=new&defVals[tt_content][colPos]='
-                               . $colPos . '&defVals[tt_content][sys_language_uid]=' . $sys_language, $this->backPath);
+                               . $colPos . '&defVals[tt_content][sys_language_uid]=' . $sys_language);
                }
                return $onClick;
        }
@@ -1708,7 +1679,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                $onClick = '';
                if ($this->doEdit && $this->getBackendUser()->recordEditAccessInternals('tt_content', $row)) {
                        // Setting onclick action for content link:
-                       $onClick = BackendUtility::editOnClick('&edit[tt_content][' . $row['uid'] . ']=edit', $this->backPath);
+                       $onClick = BackendUtility::editOnClick('&edit[tt_content][' . $row['uid'] . ']=edit');
                }
                // Return link
                return $onClick ? '<a href="#" onclick="' . htmlspecialchars($onClick)
@@ -1716,23 +1687,162 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        }
 
        /**
-        * Adds a button to edit the row in RTE wizard
+        * Get available languages for a page
+        *
+        * @param int $pageId
+        * @return array
+        */
+       protected function getAvailableLanguages($pageId) {
+               // First, select all
+               $res = $this->getPageLayoutController()->exec_languageQuery(0);
+               $langSelItems = array();
+               while ($row = $this->getDatabase()->sql_fetch_assoc($res)) {
+                       if ($this->getBackendUser()->checkLanguageAccess($row['uid'])) {
+                               $langSelItems[$row['uid']] = $row['title'];
+                       }
+               }
+               $this->getDatabase()->sql_free_result($res);
+
+               // Remove disallowed languages
+               if (count($langSelItems) > 1
+                       && !$this->getBackendUser()->user['admin']
+                       && $this->getBackendUser()->groupData['allowed_languages'] !== ''
+               ) {
+                       $allowed_languages = array_flip(explode(',', $this->getBackendUser()->groupData['allowed_languages']));
+                       if (!empty($allowed_languages)) {
+                               foreach ($langSelItems as $key => $value) {
+                                       if (!isset($allowed_languages[$key]) && $key != 0) {
+                                               unset($langSelItems[$key]);
+                                       }
+                               }
+                       }
+               }
+               // Remove disabled languages
+               $modSharedTSconfig = BackendUtility::getModTSconfig($pageId, 'mod.SHARED');
+               $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages'])
+                       ? GeneralUtility::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], TRUE)
+                       : array();
+               if (!empty($langSelItems) && !empty($disableLanguages)) {
+                       foreach ($disableLanguages as $language) {
+                               if ($language != 0 && isset($langSelItems[$language])) {
+                                       unset($langSelItems[$language]);
+                               }
+                       }
+               }
+
+               return $langSelItems;
+       }
+
+       /**
+        * Get available languages for copying into another language
+        *
+        * @param int $pageId
+        * @param int $excludeLanguage
+        * @param int $colPos
+        * @return array
+        */
+       protected function getLanguagesToCopyFrom($pageId, $excludeLanguage = NULL, $colPos = 0) {
+               $langSelItems = array();
+               if (!$this->isColumnEmpty($colPos, 0)) {
+                       $langSelItems[0] = $this->getLanguageService()->getLL('newPageContent_translateFromDefault', TRUE);
+               }
+
+               $languages = $this->getUsedLanguagesInPageAndColumn($pageId, $colPos);
+               foreach ($languages as $uid => $language) {
+                       $langSelItems[$uid] = sprintf($this->getLanguageService()->getLL('newPageContent_copyFromAnotherLang'), htmlspecialchars($language['title']));
+               }
+
+               if (isset($langSelItems[$excludeLanguage])) {
+                       unset($langSelItems[$excludeLanguage]);
+               }
+
+               return $langSelItems;
+       }
+
+       /**
+        * Get used languages in a colPos of a page
         *
-        * @param array $row The row of tt_content element
-        * @return string Button to click if you want to edit in RTE wizard.
+        * @param int $pageId
+        * @param int $colPos
+        * @return bool|\mysqli_result|object
         */
-       public function linkRTEbutton($row) {
-               $params = array();
-               $params['table'] = 'tt_content';
-               $params['uid'] = $row['uid'];
-               $params['pid'] = $row['pid'];
-               $params['field'] = 'bodytext';
-               $params['returnUrl'] = GeneralUtility::linkThisScript();
-               $RTEonClick = 'window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('wizard_rte', array('P' => $params))) . ';return false;';
-               $addButton = $this->option_showBigButtons && $this->doEdit
-                       ? $this->getPageLayoutController()->doc->t3Button($RTEonClick, $this->getLanguageService()->getLL('editInRTE'))
-                       : '';
-               return $addButton;
+       protected function getUsedLanguagesInPageAndColumn($pageId, $colPos) {
+               if (!isset($this->languagesInColumnCache[$pageId])) {
+                       $this->languagesInColumnCache[$pageId] = array();
+               }
+               if (!isset($this->languagesInColumnCache[$pageId][$colPos])) {
+                       $this->languagesInColumnCache[$pageId][$colPos] = array();
+               }
+
+               if (empty($this->languagesInColumnCache[$pageId][$colPos])) {
+                       $exQ = BackendUtility::deleteClause('tt_content') .
+                               ($this->getBackendUser()->isAdmin() ? '' : ' AND sys_language.hidden=0');
+
+                       $databaseConnection = $this->getDatabaseConnection();
+                       $res = $databaseConnection->exec_SELECTquery(
+                               'sys_language.*',
+                               'tt_content,sys_language',
+                               'tt_content.sys_language_uid=sys_language.uid AND tt_content.colPos = ' . (int)$colPos . ' AND tt_content.pid=' . (int)$pageId . $exQ .
+                               BackendUtility::versioningPlaceholderClause('tt_content'),
+                               'tt_content.sys_language_uid,sys_language.uid,sys_language.pid,sys_language.tstamp,sys_language.hidden,sys_language.title,sys_language.language_isocode,sys_language.static_lang_isocode,sys_language.flag',
+                               'sys_language.title'
+                       );
+                       while ($row = $databaseConnection->sql_fetch_assoc($res)) {
+                               $this->languagesInColumnCache[$pageId][$colPos][$row['uid']] = $row;
+                       }
+                       $databaseConnection->sql_free_result($res);
+               }
+
+               return $this->languagesInColumnCache[$pageId][$colPos];
+       }
+
+       /**
+        * Check if a column of a page for a language is empty. Translation records are ignored here!
+        *
+        * @param int $colPos
+        * @param int $languageId
+        * @return bool
+        */
+       protected function isColumnEmpty($colPos, $languageId) {
+               foreach ($this->contentElementCache[$languageId][$colPos] as $uid => $row) {
+                       if ((int)$row['l18n_parent'] === 0) {
+                               return FALSE;
+                       }
+               }
+               return TRUE;
+       }
+
+       /**
+        * Get elements for a column and a language
+        *
+        * @param int $pageId
+        * @param int $colPos
+        * @param int $languageId
+        * @return array
+        */
+       protected function getElementsFromColumnAndLanguage($pageId, $colPos, $languageId) {
+               if (!isset($this->contentElementCache[$languageId][$colPos])) {
+                       $languageId = (int)$languageId;
+                       $whereClause = 'tt_content.pid=' . (int)$pageId . ' AND tt_content.colPos=' . (int)$colPos . ' AND tt_content.sys_language_uid=' . $languageId . BackendUtility::deleteClause('tt_content');
+                       if ($languageId > 0) {
+                               $whereClause .= ' AND tt_content.l18n_parent=0 AND sys_language.uid=' . $languageId . ($this->getBackendUser()->isAdmin() ? '' : ' AND sys_language.hidden=0');
+                       }
+
+                       $databaseConnection = $this->getDatabaseConnection();
+                       $res = $databaseConnection->exec_SELECTquery(
+                               'tt_content.uid',
+                               'tt_content,sys_language',
+                               $whereClause
+                       );
+                       while ($row = $databaseConnection->sql_fetch_assoc($res)) {
+                               $this->contentElementCache[$languageId][$colPos][$row['uid']] = $row;
+                       }
+                       $databaseConnection->sql_free_result($res);
+               }
+               if (is_array($this->contentElementCache[$languageId][$colPos])) {
+                       return array_keys($this->contentElementCache[$languageId][$colPos]);
+               }
+               return array();
        }
 
        /**
@@ -1765,10 +1875,10 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        // Remove disallowed languages
                        if (count($langSelItems) > 1
                                && !$this->getBackendUser()->user['admin']
-                               && strlen($this->getBackendUser()->groupData['allowed_languages'])
+                               && $this->getBackendUser()->groupData['allowed_languages'] !== ''
                        ) {
                                $allowed_languages = array_flip(explode(',', $this->getBackendUser()->groupData['allowed_languages']));
-                               if (count($allowed_languages)) {
+                               if (!empty($allowed_languages)) {
                                        foreach ($langSelItems as $key => $value) {
                                                if (!isset($allowed_languages[$key]) && $key != 0) {
                                                        unset($langSelItems[$key]);
@@ -1781,7 +1891,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages'])
                                ? GeneralUtility::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], TRUE)
                                : array();
-                       if (count($langSelItems) && count($disableLanguages)) {
+                       if (!empty($langSelItems) && !empty($disableLanguages)) {
                                foreach ($disableLanguages as $language) {
                                        if ($language != 0 && isset($langSelItems[$language])) {
                                                unset($langSelItems[$language]);
@@ -1790,14 +1900,20 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                        }
                        // If any languages are left, make selector:
                        if (count($langSelItems) > 1) {
-                               $onChangeContent = 'window.location.href=\'' . $this->backPath . 'alt_doc.php?&edit[pages_language_overlay]['
-                                       . $id . ']=new&overrideVals[pages_language_overlay][doktype]=' . (int)$this->pageRecord['doktype']
-                                       . '&overrideVals[pages_language_overlay][sys_language_uid]=\'+this.options[this.selectedIndex].value+\'&returnUrl='
-                                       . rawurlencode(GeneralUtility::getIndpEnv('REQUEST_URI')) . '\'';
-                               return $this->getLanguageService()->getLL('new_language', TRUE)
-                                       . ': <select name="createNewLanguage" onchange="' . htmlspecialchars($onChangeContent) . '">
-                                               ' . implode('', $langSelItems) . '
-                                       </select><br /><br />';
+                               $url = BackendUtility::getModuleUrl('record_edit', array(
+                                       'edit[pages_language_overlay]['. $id . ']' => 'new',
+                                       'overrideVals[pages_language_overlay][doktype]' => (int)$this->pageRecord['doktype'],
+                                       'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
+                               ));
+                               $onChangeContent = 'window.location.href=' . GeneralUtility::quoteJSvalue($url . '&overrideVals[pages_language_overlay][sys_language_uid]=') . '+this.options[this.selectedIndex].value';
+                               return '<div class="form-inline form-inline-spaced">'
+                               . '<div class="form-group">'
+                               . '<label for="createNewLanguage">'
+                               . $this->getLanguageService()->getLL('new_language', TRUE)
+                               . '</label>'
+                               . '<select class="form-control input-sm" name="createNewLanguage" onchange="' . htmlspecialchars($onChangeContent) . '">'
+                               . implode('', $langSelItems)
+                               . '</select></div></div>';
                        }
                }
                return '';
@@ -1842,7 +1958,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         */
        protected function initializeClipboard() {
                // Start clipboard
-               $this->clipboard = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Clipboard\\Clipboard');
+               $this->clipboard = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Clipboard\Clipboard::class);
 
                // Initialize - reads the clipboard content from the user session
                $this->clipboard->initializeClipboard();
@@ -1931,7 +2047,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        public function getIcon($table, $row) {
                // Initialization
                $altText = BackendUtility::getRecordIconAltText($row, $table);
-               $icon = IconUtility::getSpriteIconForRecord($table, $row, array('title' => $altText));
+               $icon = '<span title="' . $altText . '">' . $this->iconFactory->getIconForRecord($table, $row, Icon::SIZE_SMALL)->render() . '</span>';
                $this->counter++;
                // The icon with link
                if ($this->getBackendUser()->recordEditAccessInternals($table, $row)) {
@@ -1977,29 +2093,6 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        }
 
        /**
-        * Will perform "word-wrapping" on the input string. What it does is to split by space or line break,
-        * then find any word longer than $max and if found, a hyphen is inserted.
-        * Works well on normal texts, little less well when HTML is involved (since much HTML will have
-        * long strings that will be broken).
-        *
-        * @param string $content Content to word-wrap.
-        * @param int $max Max number of chars in a word before it will be wrapped.
-        * @param string $char Character to insert when wrapping.
-        * @return string Processed output.
-        * @deprecated since 6.2 - will be removed two versions later; use CSS instead (word-break: break-all;)
-        */
-       public function wordWrapper($content, $max = 50, $char = ' -') {
-               GeneralUtility::logDeprecatedFunction();
-               $array = preg_split('/[ ' . LF . ']/', $content);
-               foreach ($array as $val) {
-                       if (strlen($val) > $max) {
-                               $content = str_replace($val, substr(chunk_split($val, $max, $char), 0, -1), $content);
-                       }
-               }
-               return $content;
-       }
-
-       /**
         * Returns icon for "no-edit" of a record.
         * Basically, the point is to signal that this record could have had an edit link if
         * the circumstances were right. A placeholder for the regular edit icon...
@@ -2008,10 +2101,8 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
         * @return string IMG tag for icon.
         */
        public function noEditIcon($label = 'noEditItems') {
-               return IconUtility::getSpriteIcon(
-                       'status-edit-read-only',
-                       array('title' => $this->getLanguageService()->getLL($label, TRUE))
-               );
+               $title = $this->getLanguageService()->getLL($label, TRUE);
+               return '<span title="' . $title . '">' . $this->iconFactory->getIcon('status-status-edit-read-only', Icon::SIZE_SMALL)->render() . '</span>';
        }
 
        /**
@@ -2036,7 +2127,7 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                // Traverse table names and set them in allowedTableNames array IF they can be read-accessed by the user.
                if (is_array($tableNames)) {
                        foreach ($tableNames as $k => $v) {
-                               if ($this->getBackendUser()->check('tables_select', $k)) {
+                               if (!$GLOBALS['TCA'][$k]['ctrl']['hideTable'] && $this->getBackendUser()->check('tables_select', $k)) {
                                        $allowedTableNames['table_' . $k] = $k;
                                }
                        }
@@ -2044,64 +2135,6 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                return $allowedTableNames;
        }
 
-       /**
-        * Checking if the RTE is available/enabled for a certain table/field and if so, it returns TRUE.
-        * Used to determine if the RTE button should be displayed.
-        *
-        * @param string $table Table name
-        * @param array $row Record row (needed, if there are RTE dependencies based on other fields in the record)
-        * @param string $field Field name
-        * @return bool Returns TRUE if the rich text editor would be enabled/available for the field name specified.
-        */
-       public function isRTEforField($table, $row, $field) {
-               $specConf = $this->getSpecConfForField($table, $row, $field);
-               if (!count($specConf)) {
-                       return FALSE;
-               }
-               $p = BackendUtility::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
-               if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) {
-                       BackendUtility::fixVersioningPid($table, $row);
-                       list($tscPID, $thePidValue) = BackendUtility::getTSCpid($table, $row['uid'], $row['pid']);
-                       // If the pid-value is not negative (that is, a pid could NOT be fetched)
-                       if ($thePidValue >= 0) {
-                               if (!isset($this->rteSetup[$tscPID])) {
-                                       $this->rteSetup[$tscPID] = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($tscPID));
-                               }
-                               $RTEtypeVal = BackendUtility::getTCAtypeValue($table, $row);
-                               $thisConfig = BackendUtility::RTEsetup($this->rteSetup[$tscPID]['properties'], $table, $field, $RTEtypeVal);
-                               if (!$thisConfig['disabled']) {
-                                       return TRUE;
-                               }
-                       }
-               }
-               return FALSE;
-       }
-
-       /**
-        * Returns "special" configuration from the "types" configuration in TCA for the record given by tablename/fieldname.
-        * Used by isRTEforField() in the process of finding whether a field has RTE enabled or not.
-        *
-        * @param string $table Table name
-        * @param array $row Record array
-        * @param string $field Field name
-        * @return array Spec. conf (if available)
-        * @access private
-        * @see isRTEforField()
-        */
-       public function getSpecConfForField($table, $row, $field) {
-               // Get types-configuration for the record:
-               $types_fieldConfig = BackendUtility::getTCAtypes($table, $row);
-               // Find the given field and return the spec key value if found:
-               if (is_array($types_fieldConfig)) {
-                       foreach ($types_fieldConfig as $vConf) {
-                               if ($vConf['field'] == $field) {
-                                       return $vConf['spec'];
-                               }
-                       }
-               }
-               return array();
-       }
-
        /*****************************************
         *
         * External renderings
@@ -2141,18 +2174,16 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
                                if ($c || GeneralUtility::inList('tt_content', $tName)) {
                                        // Add row to menu:
                                        $out .= '
-                                       <td><a href="#' . $tName . '"></a>' . IconUtility::getSpriteIconForRecord(
-                                                       $tName,
-                                                       array(),
-                                                       array('title' => $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE))
-                                               ) . '</td>';
+                                       <td><a href="#' . $tName . '" title="' . $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE) . '"></a>'
+                                               . $this->iconFactory->getIconForRecord($tName, array(), Icon::SIZE_SMALL)->render()
+                                               . '</td>';
                                        // ... and to the internal array, activeTables we also add table icon and title (for use elsewhere)
-                                       $this->activeTables[$tName] = IconUtility::getSpriteIconForRecord(
-                                                       $tName,
-                                                       array(),
-                                                       array('title' => $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE)
-                                                                       . ': ' . $c . ' ' . $this->getLanguageService()->getLL('records', TRUE))
-                                               . '&nbsp;' . $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE);
+                                       $title = $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE)
+                                               . ': ' . $c . ' ' . $this->getLanguageService()->getLL('records', TRUE);
+                                       $this->activeTables[$tName] = '<span title="' . $title. '">'
+                                               . $this->iconFactory->getIconForRecord($tName, array(), Icon::SIZE_SMALL)->render()
+                                               . '</span>'
+                                               . '&nbsp;' . $this->getLanguageService()->sL($GLOBALS['TCA'][$tName]['ctrl']['title'], TRUE);
                                }
                        }
                }
@@ -2170,12 +2201,22 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        }
 
        /**
+        * Create thumbnail code for record/field but not linked
+        *
+        * @param mixed[] $row Record array
+        * @param string $table Table (record is from)
+        * @param string $field Field name for which thumbnail are to be rendered.
+        * @return string HTML for thumbnails, if any.
+        */
+       public function getThumbCodeUnlinked($row, $table, $field) {
+               return BackendUtility::thumbCode($row, $table, $field, '', '', NULL, 0, '', '', FALSE);
+       }
+
+       /**
         * @return BackendLayoutView
         */
        protected function getBackendLayoutView() {
-               return GeneralUtility::makeInstance(
-                       'TYPO3\\CMS\\Backend\\View\\BackendLayoutView'
-               );
+               return GeneralUtility::makeInstance(BackendLayoutView::class);
        }
 
        /**
@@ -2193,24 +2234,10 @@ class PageLayoutView extends \TYPO3\CMS\Recordlist\RecordList\AbstractDatabaseRe
        }
 
        /**
-        * @return LanguageService
-        */
-       protected function getLanguageService() {
-               return $GLOBALS['LANG'];
-       }
-
-       /**
         * @return PageLayoutController
         */
        protected function getPageLayoutController() {
                return $GLOBALS['SOBE'];
        }
 
-       /**
-        * @return DocumentTemplate
-        */
-       protected function getDocumentTemplate() {
-               return $GLOBALS['TBE_TEMPLATE'];
-       }
-
 }