[!!!][TASK] Move page module function QuickEdit to EXT:compatibility7 40/51340/10
authorArtus Kolanowski <artus@ionoi.net>
Tue, 17 Jan 2017 23:46:33 +0000 (00:46 +0100)
committerBenni Mack <benni@typo3.org>
Fri, 27 Jan 2017 11:39:35 +0000 (12:39 +0100)
To follow the concept of backend apps and provide a lean core by
removing a rarely used feature, which benefit is pretty low for
the editor.

Resolves: #79364
Releases: master
Change-Id: Ic1796aa4f23507ac45b52155c66da02cffc88b3b
Reviewed-on: https://review.typo3.org/51340
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/backend/Classes/Controller/PageLayoutController.php
typo3/sysext/compatibility7/Classes/Hooks/PageLayoutActionHook.php [new file with mode: 0644]
typo3/sysext/compatibility7/ext_emconf.php
typo3/sysext/compatibility7/ext_localconf.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-79364-MovePageModuleFunctionQuickEditToCompatibility7.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Deprecation-79364-DeprecateMembersInPageLayoutController.rst [new file with mode: 0644]

index 1be89a5..8de4e4f 100644 (file)
@@ -16,19 +16,12 @@ namespace TYPO3\CMS\Backend\Controller;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Backend\Form\Exception\AccessDeniedException;
-use TYPO3\CMS\Backend\Form\FormDataCompiler;
-use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
-use TYPO3\CMS\Backend\Form\FormResultCompiler;
-use TYPO3\CMS\Backend\Form\NodeFactory;
 use TYPO3\CMS\Backend\Module\ModuleLoader;
 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
 use TYPO3\CMS\Backend\Template\ModuleTemplate;
-use TYPO3\CMS\Backend\Tree\View\ContentLayoutPagePositionMap;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Backend\View\BackendLayoutView;
 use TYPO3\CMS\Backend\View\PageLayoutView;
-use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
@@ -37,12 +30,9 @@ use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
 use TYPO3\CMS\Core\Imaging\Icon;
 use TYPO3\CMS\Core\Imaging\IconFactory;
-use TYPO3\CMS\Core\Messaging\FlashMessage;
-use TYPO3\CMS\Core\Messaging\FlashMessageService;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Type\Bitmask\Permission;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
 use TYPO3\CMS\Fluid\View\StandaloneView;
@@ -123,6 +113,7 @@ class PageLayoutController
      * Format is [tablename]:[uid] with some exceptional values for both parameters (with special meanings).
      *
      * @var string
+     * @deprecated since TYPO3 CMS 8, will be removed in TYPO3 CMS 9.
      */
     public $edit_record;
 
@@ -131,6 +122,7 @@ class PageLayoutController
      * this value as UID and we should look up the new, real uid value in sys_log.
      *
      * @var string
+     * @deprecated since TYPO3 CMS 8, will be removed in TYPO3 CMS 9.
      */
     public $new_unique_uid;
 
@@ -243,41 +235,11 @@ class PageLayoutController
     public $activeColPosList;
 
     /**
-     * @var array
-     */
-    protected $eRParts = [];
-
-    /**
      * @var string
      */
     protected $editSelect;
 
     /**
-     * @var bool
-     */
-    protected $deleteButton;
-
-    /**
-     * @var bool
-     */
-    protected $undoButton;
-
-    /**
-     * @var array
-     */
-    protected $undoButtonR;
-
-    /**
-     * @var string
-     */
-    protected $R_URI;
-
-    /**
-     * @var string
-     */
-    protected $closeUrl;
-
-    /**
      * Caches the available languages in a colPos
      *
      * @var array
@@ -367,7 +329,6 @@ class PageLayoutController
             'tt_content_showHidden' => '',
             'function' => [
                 1 => $lang->getLL('m_function_1'),
-                0 => $lang->getLL('m_function_0'),
                 2 => $lang->getLL('m_function_2')
             ],
             'language' => [
@@ -469,25 +430,26 @@ class PageLayoutController
         if (($this->modSharedTSconfig['properties']['defaultLanguageLabel'] || $this->modTSconfig['properties']['defaultLanguageLabel']) && isset($this->MOD_MENU['language'][0])) {
             $this->MOD_MENU['language'][0] = $this->modTSconfig['properties']['defaultLanguageLabel'] ? $this->modTSconfig['properties']['defaultLanguageLabel'] : $this->modSharedTSconfig['properties']['defaultLanguageLabel'];
         }
+        // Initialize the avaiable actions
+        $actions = $this->initActions();
         // Clean up settings
         $this->MOD_SETTINGS = BackendUtility::getModuleData($this->MOD_MENU, GeneralUtility::_GP('SET'), $this->moduleName);
         // For all elements to be shown in draft workspaces & to also show hidden elements by default if user hasn't disabled the option
         if ($this->getBackendUser()->workspace != 0 || $this->MOD_SETTINGS['tt_content_showHidden'] !== '0') {
             $this->MOD_SETTINGS['tt_content_showHidden'] = 1;
         }
-        $this->makeActionMenu();
+        // Make action menu from available actions
+        $this->makeActionMenu($actions);
     }
 
     /**
-     * This creates the dropdown menu with the different actions this module is able to provide.
-     * For now they are Columns, Quick Edit and Languages.
+     * Initializes the available actions this module provides
      *
-     * @return void
+     * @return array the available actions
      */
-    protected function makeActionMenu()
+    protected function initActions()
     {
-        $availableActionArray = [
-            0 => $this->getLanguageService()->getLL('m_function_0'),
+        $actions = [
             1 => $this->getLanguageService()->getLL('m_function_1'),
             2 => $this->getLanguageService()->getLL('m_function_2')
         ];
@@ -504,24 +466,40 @@ class PageLayoutController
             ->fetchColumn(0);
 
         if (!$count) {
-            unset($availableActionArray['2']);
-        }
-        // page/be_user TSconfig settings and blinding of menu-items
-        if ($this->modTSconfig['properties']['QEisDefault']) {
-            ksort($availableActionArray);
+            unset($actions['2']);
         }
-        $availableActionArray = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $availableActionArray, 'menu.function');
-        // Remove QuickEdit as option if page type is not...
-        if (!GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'] . ',6', $this->pageinfo['doktype'])) {
-            unset($availableActionArray[0]);
+        // @internal: This is an internal hook for compatibility7 only, this hook will be removed without further notice
+        $initActionHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class]['initActionHook'];
+        if (is_array($initActionHook)) {
+            foreach ($initActionHook as $hook) {
+                $params = [
+                    'actions' => &$actions
+                ];
+                GeneralUtility::callUserFunction($hook, $params, $this);
+            }
         }
+        // page/be_user TSconfig blinding of menu-items
+        $actions = BackendUtility::unsetMenuItems($this->modTSconfig['properties'], $actions, 'menu.function');
+
+        return $actions;
+    }
+
+    /**
+     * This creates the dropdown menu with the different actions this module is able to provide.
+     * For now they are Columns, Quick Edit and Languages.
+     *
+     * @param array $actions array with the available actions
+     * @return void
+     */
+    protected function makeActionMenu(array $actions)
+    {
         $actionMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
         $actionMenu->setIdentifier('actionMenu');
         $actionMenu->setLabel('');
 
         $defaultKey = null;
         $foundDefaultKey = false;
-        foreach ($availableActionArray as $key => $action) {
+        foreach ($actions as $key => $action) {
             $menuItem = $actionMenu
                 ->makeMenuItem()
                 ->setTitle($action)
@@ -794,21 +772,30 @@ class PageLayoutController
             $content .= $this->getHeaderFlashMessagesForCurrentPid();
 
             // Render the primary module content:
-            if ($this->MOD_SETTINGS['function'] == 0) {
-                // QuickEdit
-                $content .= '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) . '" method="post" enctype="multipart/form-data" name="editform" id="PageLayoutController" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
-                $content .= $this->renderQuickEdit();
-            } else {
+            if ($this->MOD_SETTINGS['function'] == 1 || $this->MOD_SETTINGS['function'] == 2) {
                 $content .= '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl($this->moduleName, ['id' => $this->id, 'imagemode' =>  $this->imagemode])) . '" id="PageLayoutController" method="post">';
                 // Page title
                 $content .= '<h1 class="t3js-title-inlineedit">' . htmlspecialchars($this->getLocalizedPageTitle()) . '</h1>';
                 // All other listings
-                $content .= $this->renderListContent();
+                $content .= $this->renderContent();
             }
             $content .= '</form>';
             $content .= $this->searchContent;
             // Setting up the buttons for the docheader
-            $this->makeButtons($this->MOD_SETTINGS['function'] == 0 ? 'quickEdit' : '');
+            $this->makeButtons();
+            // @internal: This is an internal hook for compatibility7 only, this hook will be removed without further notice
+            if ($this->MOD_SETTINGS['function'] != 1 && $this->MOD_SETTINGS['function'] != 2) {
+                $renderActionHook = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::class]['renderActionHook'];
+                if (is_array($renderActionHook)) {
+                    foreach ($renderActionHook as $hook) {
+                        $params = [
+                            'deleteButton' => $this->deleteButton,
+                            ''
+                        ];
+                        $content .= GeneralUtility::callUserFunction($hook, $params, $this);
+                    }
+                }
+            }
             // Create LanguageMenu
             $this->makeLanguageMenu();
         } else {
@@ -831,266 +818,11 @@ class PageLayoutController
     }
 
     /**
-     * Rendering the quick-edit view.
+     * Rendering content
      *
      * @return string
      */
-    public function renderQuickEdit()
-    {
-        $beUser = $this->getBackendUser();
-        $lang = $this->getLanguageService();
-        // Set the edit_record value for internal use in this function:
-        $edit_record = $this->edit_record;
-        // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine
-        if (substr($edit_record, 0, 9) == '_EDIT_COL') {
-            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
-            if ($this->MOD_SETTINGS['tt_content_showHidden']) {
-                $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
-            }
-            $statement = $queryBuilder->select('*')
-                ->from('tt_content')
-                ->orderBy('sorting')
-                ->where(
-                    $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)),
-                    $queryBuilder->expr()->eq(
-                        'colPos',
-                        $queryBuilder->createNamedParameter(substr($edit_record, 10), \PDO::PARAM_INT)
-                    ),
-                    $queryBuilder->expr()->eq(
-                        'sys_language_uid',
-                        $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)
-                    ),
-                    $queryBuilder->expr()->orX(
-                        $queryBuilder->expr()->gte(
-                            't3ver_state',
-                            $queryBuilder->createNamedParameter(
-                                (string)new VersionState(VersionState::DEFAULT_STATE),
-                                \PDO::PARAM_INT
-                            )
-                        ),
-                        $queryBuilder->expr()->eq(
-                            't3ver_wsid',
-                            $queryBuilder->createNamedParameter($beUser->workspace, \PDO::PARAM_INT)
-                        )
-                    )
-                )
-                ->execute();
-            $idListA = [];
-            while ($cRow = $statement->fetch()) {
-                $idListA[] = $cRow['uid'];
-            }
-            $url = BackendUtility::getModuleUrl('record_edit', [
-                'edit[tt_content][' . implode(',', $idListA) . ']' => 'edit',
-                'returnUrl' => $this->local_linkThisScript(['edit_record' => ''])
-            ]);
-            HttpUtility::redirect($url);
-        }
-        // If the former record edited was the creation of a NEW record, this will look up the created records uid:
-        if ($this->new_unique_uid) {
-            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_log');
-            $queryBuilder->getRestrictions()->removeAll();
-            $sys_log_row = $queryBuilder->select('tablename', 'recuid')
-                ->from('sys_log')
-                ->where(
-                    $queryBuilder->expr()->eq(
-                        'userid',
-                        $queryBuilder->createNamedParameter($beUser->user['uid'], \PDO::PARAM_INT)
-                    ),
-                    $queryBuilder->expr()->eq(
-                        'NEWid',
-                        $queryBuilder->createNamedParameter($this->new_unique_uid, \PDO::PARAM_INT)
-                    )
-                )
-                ->execute()
-                ->fetch();
-            if (is_array($sys_log_row)) {
-                $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid'];
-            }
-        }
-        $edit_record = $this->makeQuickEditMenu($edit_record);
-        // Splitting the edit-record cmd value into table/uid:
-        $this->eRParts = explode(':', $edit_record);
-        $tableName = $this->eRParts[0];
-        // Delete-button flag?
-        $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($tableName !== 'pages' && $this->EDIT_CONTENT || $tableName === 'pages' && $this->CALC_PERMS & Permission::PAGE_DELETE);
-        // If undo-button should be rendered (depends on available items in sys_history)
-        $this->undoButton = false;
-
-        // if there is no content on a page
-        // the parameter $this->eRParts[1] will be set to e.g. /new/1
-        // which is not an integer value and it will throw an exception here on certain dbms
-        // thus let's check that before as there cannot be a history for a new record
-        $this->undoButtonR = false;
-        if (MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
-            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_history');
-            $queryBuilder->getRestrictions()->removeAll();
-            $this->undoButtonR = $queryBuilder->select('tstamp')
-                ->from('sys_history')
-                ->where(
-                    $queryBuilder->expr()->eq(
-                        'tablename',
-                        $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
-                    ),
-                    $queryBuilder->expr()->eq(
-                        'recuid',
-                        $queryBuilder->createNamedParameter($this->eRParts[1], \PDO::PARAM_INT)
-                    )
-                )
-                ->orderBy('tstamp', 'DESC')
-                ->setMaxResults(1)
-                ->execute()
-                ->fetch();
-        }
-        if ($this->undoButtonR) {
-            $this->undoButton = true;
-        }
-        // Setting up the Return URL for coming back to THIS script (if links take the user to another script)
-        $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
-        $R_URL_getvars = GeneralUtility::_GET();
-        unset($R_URL_getvars['popView']);
-        unset($R_URL_getvars['new_unique_uid']);
-        $R_URL_getvars['edit_record'] = $edit_record;
-        $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars);
-
-        // Creating editing form:
-        if ($edit_record) {
-            // Splitting uid parts for special features, if new:
-            list($uidVal, $neighborRecordUid, $ex_colPos) = explode('/', $this->eRParts[1]);
-
-            if ($uidVal === 'new') {
-                $command = 'new';
-                // Page id of this new record
-                $theUid = $this->id;
-                if ($neighborRecordUid) {
-                    $theUid = $neighborRecordUid;
-                }
-            } else {
-                $command = 'edit';
-                $theUid = $uidVal;
-                // Convert $uidVal to workspace version if any:
-                $draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $tableName, $theUid, 'uid');
-                if ($draftRecord) {
-                    $theUid = $draftRecord['uid'];
-                }
-            }
-
-            // @todo: Hack because DatabaseInitializeNewRow reads from _GP directly
-            $GLOBALS['_GET']['defVals'][$tableName] = [
-                'colPos' => (int)$ex_colPos,
-                'sys_language_uid' => (int)$this->current_sys_language
-            ];
-
-            /** @var TcaDatabaseRecord $formDataGroup */
-            $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
-            /** @var FormDataCompiler $formDataCompiler */
-            $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
-            /** @var NodeFactory $nodeFactory */
-            $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
-
-            try {
-                $formDataCompilerInput = [
-                    'tableName' => $tableName,
-                    'vanillaUid' => (int)$theUid,
-                    'command' => $command,
-                ];
-                $formData = $formDataCompiler->compile($formDataCompilerInput);
-
-                if ($command !== 'new') {
-                    BackendUtility::lockRecords($tableName, $formData['databaseRow']['uid'], $tableName === 'tt_content' ? $formData['databaseRow']['pid'] : 0);
-                }
-
-                $formData['renderType'] = 'outerWrapContainer';
-                $formResult = $nodeFactory->create($formData)->render();
-
-                $panel = $formResult['html'];
-                $formResult['html'] = '';
-
-                /** @var FormResultCompiler $formResultCompiler */
-                $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
-                $formResultCompiler->mergeResult($formResult);
-
-                $row = $formData['databaseRow'];
-                $new_unique_uid = '';
-                if ($command === 'new') {
-                    $new_unique_uid = $row['uid'];
-                }
-
-                // Add hidden fields:
-                if ($uidVal == 'new') {
-                    $panel .= '<input type="hidden" name="data[' . $tableName . '][' . $row['uid'] . '][pid]" value="' . $row['pid'] . '" />';
-                }
-                $redirect = ($uidVal == 'new' ? BackendUtility::getModuleUrl(
-                    $this->moduleName,
-                    ['id' => $this->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl]
-                ) : $this->R_URI);
-                $panel .= '
-                    <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />
-                    <input type="hidden" name="edit_record" value="' . $edit_record . '" />
-                    <input type="hidden" name="redirect" value="' . htmlspecialchars($redirect) . '" />
-                    ';
-                // Add JavaScript as needed around the form:
-                $content = $formResultCompiler->addCssFiles() . $panel . $formResultCompiler->printNeededJSFunctions();
-
-                // Display "is-locked" message:
-                if ($command === 'edit') {
-                    $lockInfo = BackendUtility::isRecordLocked($tableName, $formData['databaseRow']['uid']);
-                    if ($lockInfo) {
-                        /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
-                        $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $lockInfo['msg'], '', FlashMessage::WARNING);
-                        /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
-                        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
-                        /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
-                        $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
-                        $defaultFlashMessageQueue->enqueue($flashMessage);
-                    }
-                }
-            } catch (AccessDeniedException $e) {
-                // If no edit access, print error message:
-                $content = '<h2>' . htmlspecialchars($lang->getLL('noAccess')) . '</h2>';
-                $content .= '<div>' . $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : '') . '</div>';
-            }
-        } else {
-            // If no edit access, print error message:
-            $content = '<h2>' . $lang->getLL('noAccess') . '</h2>';
-            $content .= '<div>' . $lang->getLL('noAccess_msg') . '</div>';
-        }
-
-        // Element selection matrix:
-        if ($tableName === 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
-            $content .= '<h2>' . $lang->getLL('CEonThisPage') . '</h2>';
-            // PositionMap
-            $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class);
-            $posMap->cur_sys_language = $this->current_sys_language;
-            $content .= $posMap->printContentElementColumns(
-                $this->id,
-                $this->eRParts[1],
-                $this->colPosList,
-                $this->MOD_SETTINGS['tt_content_showHidden'],
-                $this->R_URI
-            );
-            // Toggle hidden ContentElements
-            $numberOfHiddenElements = $this->getNumberOfHiddenElements();
-            if ($numberOfHiddenElements) {
-                $content .= '<div class="checkbox">';
-                $content .= '<label for="checkTt_content_showHidden">';
-                $content .= BackendUtility::getFuncCheck($this->id, 'SET[tt_content_showHidden]', $this->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"');
-                $content .= (!$numberOfHiddenElements ? ('<span class="text-muted">' . htmlspecialchars($lang->getLL('hiddenCE')) . '</span>') : htmlspecialchars($lang->getLL('hiddenCE')) . ' (' . $numberOfHiddenElements . ')');
-                $content .= '</label>';
-                $content .= '</div>';
-            }
-            // CSH
-            $content .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', null, '<span class="btn btn-default btn-sm">|</span>');
-        }
-
-        return $content;
-    }
-
-    /**
-     * Rendering all other listings than QuickEdit
-     *
-     * @return string
-     */
-    public function renderListContent()
+    public function renderContent()
     {
         $this->moduleTemplate->getPageRenderer()->loadJquery();
         $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
@@ -1256,11 +988,17 @@ class PageLayoutController
     /**
      * This creates the buttons for die modules
      *
-     * @param string $function Identifier for function of module
      * @return void
      */
-    protected function makeButtons($function = '')
+    protected function makeButtons()
     {
+        if ($this->MOD_SETTINGS['function'] == 1 || $this->MOD_SETTINGS['function'] == 2) {
+            // Add CSH (Context Sensitive Help) icon to tool bar
+            $contextSensitiveHelpButton = $this->buttonBar->makeHelpButton()
+                ->setModuleName($this->descrTable)
+                ->setFieldName('columns_' . $this->controller->MOD_SETTINGS['function']);
+            $this->buttonBar->addButton($contextSensitiveHelpButton);
+        }
         $lang = $this->getLanguageService();
         // View page
         if (!VersionState::cast($this->pageinfo['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER)) {
@@ -1297,20 +1035,6 @@ class PageLayoutController
             $this->buttonBar->addButton($clearCacheButton, ButtonBar::BUTTON_POSITION_RIGHT, 1);
         }
         if (!$this->modTSconfig['properties']['disableIconToolbar']) {
-            // Move record
-            if (MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
-                $urlParameters = [
-                    'table' => $this->eRParts[0],
-                    'uid' => $this->eRParts[1],
-                    'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
-                ];
-                $moveButton = $this->buttonBar->makeLinkButton()
-                    ->setHref(BackendUtility::getModuleUrl('move_element', $urlParameters))
-                    ->setTitle($lang->getLL('move_' . ($this->eRParts[0] == 'tt_content' ? 'record' : 'page')))
-                    ->setIcon($this->iconFactory->getIcon('actions-' . ($this->eRParts[0] == 'tt_content' ? 'document' : 'page') . '-move', Icon::SIZE_SMALL));
-                $this->buttonBar->addButton($moveButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
-            }
-
             // Edit page properties and page language overlay icons
             if ($this->pageIsNotLockedForEditors() && $this->getBackendUser()->checkLanguageAccess(0)) {
                 // Edit localized page_language_overlay only when one specific language is selected
@@ -1368,100 +1092,6 @@ class PageLayoutController
                     ->setIcon($this->iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL));
                 $this->buttonBar->addButton($editPageButton, ButtonBar::BUTTON_POSITION_LEFT, 3);
             }
-
-            // Add CSH (Context Sensitive Help) icon to tool bar
-            $contextSensitiveHelpButton = $this->buttonBar->makeHelpButton()
-                ->setModuleName($this->descrTable)
-                ->setFieldName(($function === 'quickEdit' ? 'quickEdit' : 'columns_' . $this->MOD_SETTINGS['function']));
-            $this->buttonBar->addButton($contextSensitiveHelpButton);
-
-            // QuickEdit
-            if ($function == 'quickEdit') {
-                // Close Record
-                $closeButton = $this->buttonBar->makeLinkButton()
-                    ->setHref('#')
-                    ->setOnClick('jumpToUrl(' . GeneralUtility::quoteJSvalue($this->closeUrl) . '); return false;')
-                    ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
-                    ->setIcon($this->iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL));
-                $this->buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 0);
-
-                // Save Record
-                $saveButtonDropdown = $this->buttonBar->makeSplitButton();
-                $saveButton = $this->buttonBar->makeInputButton()
-                    ->setName('_savedok')
-                    ->setValue('1')
-                    ->setForm('PageLayoutController')
-                    ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
-                    ->setIcon($this->iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL));
-                $saveButtonDropdown->addItem($saveButton);
-                $saveAndCloseButton = $this->buttonBar->makeInputButton()
-                    ->setName('_saveandclosedok')
-                    ->setValue('1')
-                    ->setForm('PageLayoutController')
-                    ->setOnClick('document.editform.redirect.value=\'' . $this->closeUrl . '\';')
-                    ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc'))
-                    ->setIcon($this->iconFactory->getIcon('actions-document-save-close', Icon::SIZE_SMALL));
-                $saveButtonDropdown->addItem($saveAndCloseButton);
-                $saveAndShowPageButton = $this->buttonBar->makeInputButton()
-                    ->setName('_savedokview')
-                    ->setValue('1')
-                    ->setForm('PageLayoutController')
-                    ->setOnClick('document.editform.redirect.value+=\'&popView=1\';')
-                    ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveDocShow'))
-                    ->setIcon($this->iconFactory->getIcon('actions-document-save-view', Icon::SIZE_SMALL));
-                $saveButtonDropdown->addItem($saveAndShowPageButton);
-                $this->buttonBar->addButton($saveButtonDropdown, ButtonBar::BUTTON_POSITION_LEFT, 1);
-
-                // Delete record
-                if ($this->deleteButton) {
-                    $dataAttributes = [];
-                    $dataAttributes['table'] = $this->eRParts[0];
-                    $dataAttributes['uid'] = $this->eRParts[1];
-                    $dataAttributes['return-url'] = BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id;
-                    $deleteButton = $this->buttonBar->makeLinkButton()
-                        ->setHref('#')
-                        ->setClasses('t3js-editform-delete-record')
-                        ->setDataAttributes($dataAttributes)
-                        ->setTitle($lang->getLL('deleteItem'))
-                        ->setIcon($this->iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL));
-                    $this->buttonBar->addButton($deleteButton, ButtonBar::BUTTON_POSITION_LEFT, 4);
-                }
-
-                // History
-                if ($this->undoButton) {
-                    $undoButton = $this->buttonBar->makeLinkButton()
-                        ->setHref('#')
-                        ->setOnClick('window.location.href=' .
-                            GeneralUtility::quoteJSvalue(
-                                BackendUtility::getModuleUrl(
-                                    'record_history',
-                                    [
-                                        'element' => $this->eRParts[0] . ':' . $this->eRParts[1],
-                                        'revert' => 'ALL_FIELDS',
-                                        'returnUrl' => $this->R_URI,
-                                    ]
-                                )
-                            ) . '; return false;')
-                        ->setTitle(sprintf($lang->getLL('undoLastChange'), BackendUtility::calcAge($GLOBALS['EXEC_TIME'] - $this->undoButtonR['tstamp'], $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears'))))
-                        ->setIcon($this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL));
-                    $this->buttonBar->addButton($undoButton, ButtonBar::BUTTON_POSITION_LEFT, 5);
-                    $historyButton = $this->buttonBar->makeLinkButton()
-                        ->setHref('#')
-                        ->setOnClick('jumpToUrl(' .
-                            GeneralUtility::quoteJSvalue(
-                                BackendUtility::getModuleUrl(
-                                    'record_history',
-                                    [
-                                            'element' => $this->eRParts[0] . ':' . $this->eRParts[1],
-                                            'returnUrl' => $this->R_URI,
-                                        ]
-                                ) . '#latest'
-                            ) . ');return false;')
-                        ->setTitle($lang->getLL('recordHistory'))
-                        ->setIcon($this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL));
-                    $this->buttonBar->addButton($historyButton, ButtonBar::BUTTON_POSITION_LEFT, 3);
-                }
-            }
         }
     }
 
@@ -1610,165 +1240,6 @@ class PageLayoutController
     }
 
     /**
-     * @param $edit_record array
-     *
-     * @return array
-     */
-    protected function makeQuickEditMenu($edit_record)
-    {
-        $lang = $this->getLanguageService();
-        $beUser = $this->getBackendUser();
-
-        $quickEditMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
-        $quickEditMenu->setIdentifier('quickEditMenu');
-        $quickEditMenu->setLabel('');
-
-        // Setting close url/return url for exiting this script:
-        // Goes to 'Columns' view if close is pressed (default)
-        $this->closeUrl = $this->local_linkThisScript(['SET' => ['function' => 1]]);
-        if ($this->returnUrl) {
-            $this->closeUrl = $this->returnUrl;
-        }
-        $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : '';
-
-        // Creating the selector box, allowing the user to select which element to edit:
-        $isSelected = 0;
-        $languageOverlayRecord = '';
-        if ($this->current_sys_language) {
-            list($languageOverlayRecord) = BackendUtility::getRecordsByField(
-                'pages_language_overlay',
-                'pid',
-                $this->id,
-                'AND sys_language_uid=' . (int)$this->current_sys_language
-            );
-        }
-        if (is_array($languageOverlayRecord)) {
-            $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid'];
-            $isSelected += (int)$edit_record == $inValue;
-            $menuItem = $quickEditMenu->makeMenuItem()
-                ->setTitle('[ ' . $lang->getLL('editLanguageHeader') . ' ]')
-                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
-                ->setActive($edit_record == $inValue);
-            $quickEditMenu->addMenuItem($menuItem);
-        } else {
-            $inValue = 'pages:' . $this->id;
-            $isSelected += (int)$edit_record == $inValue;
-            $menuItem = $quickEditMenu->makeMenuItem()
-                ->setTitle('[ ' . $lang->getLL('editPageProperties') . ' ]')
-                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
-                ->setActive($edit_record == $inValue);
-            $quickEditMenu->addMenuItem($menuItem);
-        }
-
-        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
-        if ($this->MOD_SETTINGS['tt_content_showHidden']) {
-            $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
-        }
-        $queryBuilder->select('*')
-            ->from('tt_content')
-            ->where(
-                $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)),
-                $queryBuilder->expr()->eq(
-                    'sys_language_uid',
-                    $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT)
-                ),
-                $queryBuilder->expr()->in(
-                    'colPos',
-                    $queryBuilder->createNamedParameter(
-                        GeneralUtility::intExplode(',', $this->colPosList, true),
-                        Connection::PARAM_INT_ARRAY
-                    )
-                ),
-                $queryBuilder->expr()->orX(
-                    $queryBuilder->expr()->gte(
-                        't3ver_state',
-                        $queryBuilder->createNamedParameter(
-                            (string)new VersionState(VersionState::DEFAULT_STATE),
-                            \PDO::PARAM_INT
-                        )
-                    ),
-                    $queryBuilder->expr()->eq(
-                        't3ver_wsid',
-                        $queryBuilder->createNamedParameter(
-                            (string)new VersionState(VersionState::DEFAULT_STATE),
-                            \PDO::PARAM_INT
-                        )
-                    )
-                )
-            )
-            ->orderBy('colPos')
-            ->addOrderBy('sorting');
-        if (!$beUser->user['admin']) {
-            $queryBuilder->andWhere(
-                $queryBuilder->expr()->eq(
-                    'editlock',
-                    $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
-                )
-            );
-        }
-        $statement = $queryBuilder->execute();
-        $colPos = null;
-        $first = 1;
-        // Page is the pid if no record to put this after.
-        $prev = $this->id;
-        while ($cRow = $statement->fetch()) {
-            BackendUtility::workspaceOL('tt_content', $cRow);
-            if (is_array($cRow)) {
-                if ($first) {
-                    if (!$edit_record) {
-                        $edit_record = 'tt_content:' . $cRow['uid'];
-                    }
-                    $first = 0;
-                }
-                if (!isset($colPos) || $cRow['colPos'] !== $colPos) {
-                    $colPos = $cRow['colPos'];
-                    $menuItem = $quickEditMenu->makeMenuItem()
-                        ->setTitle(' ')
-                        ->setHref('#');
-                    $quickEditMenu->addMenuItem($menuItem);
-                    $menuItem = $quickEditMenu->makeMenuItem()
-                        ->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos)) . ':__')
-                        ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr);
-                    $quickEditMenu->addMenuItem($menuItem);
-                }
-                $inValue = 'tt_content:' . $cRow['uid'];
-                $isSelected += (int)$edit_record == $inValue;
-                $menuItem = $quickEditMenu->makeMenuItem()
-                    ->setTitle(GeneralUtility::fixed_lgd_cs(($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext'])), $beUser->uc['titleLen']))
-                    ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
-                    ->setActive($edit_record == $inValue);
-                $quickEditMenu->addMenuItem($menuItem);
-                $prev = -$cRow['uid'];
-            }
-        }
-        // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element:
-        if (!$edit_record) {
-            $edit_record = 'tt_content:new/' . $prev . '/' . $colPos;
-            $inValue = 'tt_content:new/' . $prev . '/' . $colPos;
-            $isSelected += (int)$edit_record == $inValue;
-            $menuItem = $quickEditMenu->makeMenuItem()
-                ->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')
-                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
-                ->setActive($edit_record == $inValue);
-            $quickEditMenu->addMenuItem($menuItem);
-        }
-        // If none is yet selected...
-        if (!$isSelected) {
-            $menuItem = $quickEditMenu->makeMenuItem()
-                ->setTitle('__________')
-                ->setHref('#');
-            $quickEditMenu->addMenuItem($menuItem);
-            $menuItem = $quickEditMenu->makeMenuItem()
-                ->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')
-                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $edit_record . $retUrlStr)
-                ->setActive($edit_record == $inValue);
-            $quickEditMenu->addMenuItem($menuItem);
-        }
-        $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu);
-        return $edit_record;
-    }
-
-    /**
      * Make the LanguageMenu
      *
      * @return void
diff --git a/typo3/sysext/compatibility7/Classes/Hooks/PageLayoutActionHook.php b/typo3/sysext/compatibility7/Classes/Hooks/PageLayoutActionHook.php
new file mode 100644 (file)
index 0000000..6a2d055
--- /dev/null
@@ -0,0 +1,682 @@
+<?php
+namespace TYPO3\CMS\Compatibility7\Hooks;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Controller\PageLayoutController;
+use TYPO3\CMS\Backend\Form\FormDataCompiler;
+use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
+use TYPO3\CMS\Backend\Form\FormResultCompiler;
+use TYPO3\CMS\Backend\Form\NodeFactory;
+use TYPO3\CMS\Backend\Template\Components\ButtonBar;
+use TYPO3\CMS\Backend\Tree\View\ContentLayoutPagePositionMap;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Database\Connection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Messaging\FlashMessage;
+use TYPO3\CMS\Core\Messaging\FlashMessageService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Versioning\VersionState;
+
+/**
+ * Adds the action `QuickEdit to the module `Web > Layout`
+ */
+class PageLayoutActionHook
+{
+
+    /**
+     * @var bool
+     */
+    protected $undoButton;
+
+    /**
+     * @var array
+     */
+    protected $undoButtonR;
+
+    /**
+     * @var bool
+     */
+    protected $deleteButton;
+
+    /**
+     * @var string
+     */
+    protected $closeUrl;
+
+    /**
+     * @var array
+     */
+    protected $eRParts = [];
+
+    /**
+     * The name of the module
+     *
+     * @var string
+     */
+    protected $moduleName = 'web_layout';
+
+    /**
+     * @var string
+     */
+    protected $R_URI;
+
+    /**
+     * @var PageLayoutController
+     */
+    protected $controller;
+
+    /**
+     * Initializes the action
+     *
+     * @param array $parameters the hook parameters
+     * @param PageLayoutController $controller the page layout controller
+     * @return void
+     */
+    public function initAction(array $parameters, PageLayoutController $controller)
+    {
+        $this->controller = $controller;
+        // Add function to MOD_MENU
+        $this->controller->MOD_MENU['function'] = array_slice($this->controller->MOD_MENU['function'], 0, 1, true)
+            + ['0' => $this->getLanguageService()->getLL('m_function_0')] + $this->controller->MOD_MENU['function'];
+        // Remove QuickEdit as option if page type is not...
+        if (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['FE']['content_doktypes'] . ',6', $this->controller->pageinfo['doktype'])) {
+            array_unshift($parameters['actions'], $this->getLanguageService()->getLL('m_function_0'));
+        }
+        // TSconfig settings and blinding of menu-items
+        if ($this->controller->modTSconfig['properties']['QEisDefault']) {
+            ksort($parameters['actions']);
+        }
+    }
+
+    /**
+     * Renders the content of the action
+     *
+     * @param array $parameters the hook parameters
+     * @param PageLayoutController $controller the page layout controller
+     * @return string the module content
+     */
+    public function renderAction(array $parameters, PageLayoutController $controller)
+    {
+        $this->controller = $controller;
+
+        $content = $this->renderContent();
+        $this->makeButtons();
+
+        return $content;
+    }
+
+    /**
+     * Makes the action buttons
+     *
+     * @return void
+     */
+    protected function makeButtons()
+    {
+        $buttonBar = $this->controller->getModuleTemplate()->getDocHeaderComponent()->getButtonBar();
+        $iconFactory = $this->controller->getModuleTemplate()->getIconFactory();
+        $lang = $this->getLanguageService();
+        // Add CSH (Context Sensitive Help) icon to tool bar
+        $contextSensitiveHelpButton = $buttonBar->makeHelpButton()
+            ->setModuleName($this->controller->descrTable)
+            ->setFieldName('quickEdit');
+        $buttonBar->addButton($contextSensitiveHelpButton);
+
+        if (!$this->controller->modTSconfig['properties']['disableIconToolbar']) {
+            // Move record
+            if (MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
+                $urlParameters = [
+                    'table' => $this->eRParts[0],
+                    'uid' => $this->eRParts[1],
+                    'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI')
+                ];
+                $moveButton = $buttonBar->makeLinkButton()
+                    ->setHref(BackendUtility::getModuleUrl('move_element', $urlParameters))
+                    ->setTitle($lang->getLL('move_' . ($this->eRParts[0] == 'tt_content' ? 'record' : 'page')))
+                    ->setIcon($iconFactory->getIcon('actions-' . ($this->eRParts[0] == 'tt_content' ? 'document' : 'page') . '-move', Icon::SIZE_SMALL));
+                $buttonBar->addButton($moveButton, ButtonBar::BUTTON_POSITION_LEFT, 2);
+            }
+        }
+
+        // Close Record
+        $closeButton = $buttonBar->makeLinkButton()
+            ->setHref('#')
+            ->setOnClick('jumpToUrl(' . GeneralUtility::quoteJSvalue($this->closeUrl) . '); return false;')
+            ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
+            ->setIcon($iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL));
+        $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 0);
+
+        // Save Record
+        $saveButtonDropdown = $buttonBar->makeSplitButton();
+        $saveButton = $buttonBar->makeInputButton()
+            ->setName('_savedok')
+            ->setValue('1')
+            ->setForm('PageLayoutController')
+            ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
+            ->setIcon($iconFactory->getIcon('actions-document-save', Icon::SIZE_SMALL));
+        $saveButtonDropdown->addItem($saveButton);
+        $saveAndCloseButton = $buttonBar->makeInputButton()
+            ->setName('_saveandclosedok')
+            ->setValue('1')
+            ->setForm('PageLayoutController')
+            ->setOnClick('document.editform.redirect.value=\'' . $this->closeUrl . '\';')
+            ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveCloseDoc'))
+            ->setIcon($iconFactory->getIcon('actions-document-save-close', Icon::SIZE_SMALL));
+        $saveButtonDropdown->addItem($saveAndCloseButton);
+        $saveAndShowPageButton = $buttonBar->makeInputButton()
+            ->setName('_savedokview')
+            ->setValue('1')
+            ->setForm('PageLayoutController')
+            ->setOnClick('document.editform.redirect.value+=\'&popView=1\';')
+            ->setTitle($lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveDocShow'))
+            ->setIcon($iconFactory->getIcon('actions-document-save-view', Icon::SIZE_SMALL));
+        $saveButtonDropdown->addItem($saveAndShowPageButton);
+        $buttonBar->addButton($saveButtonDropdown, ButtonBar::BUTTON_POSITION_LEFT, 1);
+
+        // Delete record
+        if ($this->deleteButton) {
+            $dataAttributes = [];
+            $dataAttributes['table'] = $this->eRParts[0];
+            $dataAttributes['uid'] = $this->eRParts[1];
+            $dataAttributes['return-url'] = BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->controller->id;
+            $deleteButton = $buttonBar->makeLinkButton()
+                ->setHref('#')
+                ->setClasses('t3js-editform-delete-record')
+                ->setDataAttributes($dataAttributes)
+                ->setTitle($lang->getLL('deleteItem'))
+                ->setIcon($iconFactory->getIcon('actions-edit-delete', Icon::SIZE_SMALL));
+            $buttonBar->addButton($deleteButton, ButtonBar::BUTTON_POSITION_LEFT, 4);
+        }
+
+        // History
+        if ($this->undoButton) {
+            $undoButton = $buttonBar->makeLinkButton()
+                ->setHref('#')
+                ->setOnClick('window.location.href=' .
+                    GeneralUtility::quoteJSvalue(
+                        BackendUtility::getModuleUrl(
+                            'record_history',
+                            [
+                                'element' => $this->eRParts[0] . ':' . $this->eRParts[1],
+                                'revert' => 'ALL_FIELDS',
+                                'returnUrl' => $this->R_URI,
+                            ]
+                        )
+                    ) . '; return false;')
+                ->setTitle(sprintf($lang->getLL('undoLastChange'), BackendUtility::calcAge($GLOBALS['EXEC_TIME'] - $this->undoButtonR['tstamp'], $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.minutesHoursDaysYears'))))
+                ->setIcon($iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL));
+            $buttonBar->addButton($undoButton, ButtonBar::BUTTON_POSITION_LEFT, 5);
+            $historyButton = $buttonBar->makeLinkButton()
+                ->setHref('#')
+                ->setOnClick('jumpToUrl(' .
+                    GeneralUtility::quoteJSvalue(
+                        BackendUtility::getModuleUrl(
+                            'record_history',
+                            [
+                                'element' => $this->eRParts[0] . ':' . $this->eRParts[1],
+                                'returnUrl' => $this->R_URI,
+                            ]
+                            ) . '#latest'
+                        ) . ');return false;')
+                ->setTitle($lang->getLL('recordHistory'))
+                ->setIcon($iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL));
+            $buttonBar->addButton($historyButton, ButtonBar::BUTTON_POSITION_LEFT, 3);
+        }
+    }
+
+    /**
+     * Makes the action menu
+     *
+     * @param array $edit_record the record to make the menu for
+     *
+     * @return array
+     */
+    protected function makeMenu($edit_record)
+    {
+        $lang = $this->getLanguageService();
+        $beUser = $this->getBackendUser();
+
+        $quickEditMenu = $this->controller->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
+        $quickEditMenu->setIdentifier('quickEditMenu');
+        $quickEditMenu->setLabel('');
+
+        // Setting close url/return url for exiting this script:
+        // Goes to 'Columns' view if close is pressed (default)
+        $this->closeUrl = $this->controller->local_linkThisScript(['SET' => ['function' => 1]]);
+        if ($this->returnUrl) {
+            $this->closeUrl = $this->returnUrl;
+        }
+        $retUrlStr = $this->returnUrl ? '&returnUrl=' . rawurlencode($this->returnUrl) : '';
+
+        // Creating the selector box, allowing the user to select which element to edit:
+        $isSelected = 0;
+        $languageOverlayRecord = '';
+        if ($this->current_sys_language) {
+            list($languageOverlayRecord) = BackendUtility::getRecordsByField(
+                'pages_language_overlay',
+                'pid',
+                $this->id,
+                'AND sys_language_uid=' . (int)$this->current_sys_language
+            );
+        }
+        if (is_array($languageOverlayRecord)) {
+            $inValue = 'pages_language_overlay:' . $languageOverlayRecord['uid'];
+            $isSelected += (int)$edit_record == $inValue;
+            $menuItem = $quickEditMenu->makeMenuItem()
+                ->setTitle('[ ' . $lang->getLL('editLanguageHeader') . ' ]')
+                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
+                ->setActive($edit_record == $inValue);
+            $quickEditMenu->addMenuItem($menuItem);
+        } else {
+            $inValue = 'pages:' . $this->id;
+            $isSelected += (int)$edit_record == $inValue;
+            $menuItem = $quickEditMenu->makeMenuItem()
+                ->setTitle('[ ' . $lang->getLL('editPageProperties') . ' ]')
+                ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->id . '&edit_record=' . $inValue . $retUrlStr)
+                ->setActive($edit_record == $inValue);
+            $quickEditMenu->addMenuItem($menuItem);
+        }
+
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
+        if ($this->controller->MOD_SETTINGS['tt_content_showHidden']) {
+            $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+        }
+        $queryBuilder->select('*')
+            ->from('tt_content')
+            ->where(
+                $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->controller->id, \PDO::PARAM_INT)),
+                $queryBuilder->expr()->eq(
+                    'sys_language_uid',
+                    $queryBuilder->createNamedParameter($this->controller->current_sys_language, \PDO::PARAM_INT)
+                    ),
+                $queryBuilder->expr()->in(
+                    'colPos',
+                    $queryBuilder->createNamedParameter(
+                        GeneralUtility::intExplode(',', $this->controller->colPosList, true),
+                        Connection::PARAM_INT_ARRAY
+                        )
+                    ),
+                $queryBuilder->expr()->orX(
+                    $queryBuilder->expr()->gte(
+                        't3ver_state',
+                        $queryBuilder->createNamedParameter(
+                            (string)new VersionState(VersionState::DEFAULT_STATE),
+                            \PDO::PARAM_INT
+                            )
+                        ),
+                    $queryBuilder->expr()->eq(
+                        't3ver_wsid',
+                        $queryBuilder->createNamedParameter(
+                            (string)new VersionState(VersionState::DEFAULT_STATE),
+                            \PDO::PARAM_INT
+                            )
+                        )
+                    )
+                )
+                ->orderBy('colPos')
+                ->addOrderBy('sorting');
+        if (!$beUser->user['admin']) {
+            $queryBuilder->andWhere(
+                    $queryBuilder->expr()->eq(
+                        'editlock',
+                        $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+                    )
+                );
+        }
+        $statement = $queryBuilder->execute();
+        $colPos = null;
+        $first = 1;
+            // Page is the pid if no record to put this after.
+            $prev = $this->controller->id;
+        while ($cRow = $statement->fetch()) {
+            BackendUtility::workspaceOL('tt_content', $cRow);
+            if (is_array($cRow)) {
+                if ($first) {
+                    if (!$edit_record) {
+                        $edit_record = 'tt_content:' . $cRow['uid'];
+                    }
+                    $first = 0;
+                }
+                if (!isset($colPos) || $cRow['colPos'] !== $colPos) {
+                    $colPos = $cRow['colPos'];
+                    $menuItem = $quickEditMenu->makeMenuItem()
+                            ->setTitle(' ')
+                            ->setHref('#');
+                    $quickEditMenu->addMenuItem($menuItem);
+                    $menuItem = $quickEditMenu->makeMenuItem()
+                            ->setTitle('__' . $lang->sL(BackendUtility::getLabelFromItemlist('tt_content', 'colPos', $colPos)) . ':__')
+                            ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->controller->id . '&edit_record=_EDIT_COL:' . $colPos . $retUrlStr);
+                    $quickEditMenu->addMenuItem($menuItem);
+                }
+                $inValue = 'tt_content:' . $cRow['uid'];
+                $isSelected += (int)$edit_record == $inValue;
+                $menuItem = $quickEditMenu->makeMenuItem()
+                        ->setTitle(GeneralUtility::fixed_lgd_cs(($cRow['header'] ? $cRow['header'] : '[' . $lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.no_title') . '] ' . strip_tags($cRow['bodytext'])), $beUser->uc['titleLen']))
+                        ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->controller->id . '&edit_record=' . $inValue . $retUrlStr)
+                        ->setActive($edit_record == $inValue);
+                $quickEditMenu->addMenuItem($menuItem);
+                $prev = -$cRow['uid'];
+            }
+        }
+            // If edit_record is not set (meaning, no content elements was found for this language) we simply set it to create a new element:
+            if (!$edit_record) {
+                $edit_record = 'tt_content:new/' . $prev . '/' . $colPos;
+                $inValue = 'tt_content:new/' . $prev . '/' . $colPos;
+                $isSelected += (int)$edit_record == $inValue;
+                $menuItem = $quickEditMenu->makeMenuItem()
+                    ->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')
+                    ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->controller->id . '&edit_record=' . $inValue . $retUrlStr)
+                    ->setActive($edit_record == $inValue);
+                $quickEditMenu->addMenuItem($menuItem);
+            }
+            // If none is yet selected...
+            if (!$isSelected) {
+                $menuItem = $quickEditMenu->makeMenuItem()
+                    ->setTitle('__________')
+                    ->setHref('#');
+                $quickEditMenu->addMenuItem($menuItem);
+                $menuItem = $quickEditMenu->makeMenuItem()
+                    ->setTitle('[ ' . $lang->getLL('newLabel') . ' ]')
+                    ->setHref(BackendUtility::getModuleUrl($this->moduleName) . '&id=' . $this->controller->id . '&edit_record=' . $edit_record . $retUrlStr)
+                    ->setActive($edit_record == $inValue);
+                $quickEditMenu->addMenuItem($menuItem);
+            }
+        $this->controller->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry()->addMenu($quickEditMenu);
+        return $edit_record;
+    }
+
+    /**
+     * Renders the action content
+     *
+     * @return string the content
+     */
+    protected function renderContent()
+    {
+        $beUser = $this->getBackendUser();
+        $lang = $this->getLanguageService();
+        // Set the edit_record value for internal use in this function:
+        $edit_record = $this->controller->edit_record;
+        // If a command to edit all records in a column is issue, then select all those elements, and redirect to FormEngine
+        if (substr($edit_record, 0, 9) == '_EDIT_COL') {
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
+            if ($this->controller->MOD_SETTINGS['tt_content_showHidden']) {
+                $queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
+            }
+            $statement = $queryBuilder->select('*')
+                ->from('tt_content')
+                ->orderBy('sorting')
+                ->where(
+                    $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->controller->id, \PDO::PARAM_INT)),
+                    $queryBuilder->expr()->eq(
+                        'colPos',
+                        $queryBuilder->createNamedParameter(substr($edit_record, 10), \PDO::PARAM_INT)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        'sys_language_uid',
+                        $queryBuilder->createNamedParameter($this->controller->current_sys_language, \PDO::PARAM_INT)
+                    ),
+                    $queryBuilder->expr()->orX(
+                        $queryBuilder->expr()->gte(
+                            't3ver_state',
+                            $queryBuilder->createNamedParameter(
+                                (string)new VersionState(VersionState::DEFAULT_STATE),
+                                \PDO::PARAM_INT
+                            )
+                        ),
+                        $queryBuilder->expr()->eq(
+                            't3ver_wsid',
+                            $queryBuilder->createNamedParameter($beUser->workspace, \PDO::PARAM_INT)
+                        )
+                    )
+                )
+                ->execute();
+            $idListA = [];
+            while ($cRow = $statement->fetch()) {
+                $idListA[] = $cRow['uid'];
+            }
+            $url = BackendUtility::getModuleUrl('record_edit', [
+                'edit[tt_content][' . implode(',', $idListA) . ']' => 'edit',
+                'returnUrl' => $this->controller->local_linkThisScript(['edit_record' => ''])
+            ]);
+            HttpUtility::redirect($url);
+        }
+        // If the former record edited was the creation of a NEW record, this will look up the created records uid:
+        if ($this->controller->new_unique_uid) {
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_log');
+            $queryBuilder->getRestrictions()->removeAll();
+            $sys_log_row = $queryBuilder->select('tablename', 'recuid')
+                ->from('sys_log')
+                ->where(
+                    $queryBuilder->expr()->eq(
+                        'userid',
+                        $queryBuilder->createNamedParameter($beUser->user['uid'], \PDO::PARAM_INT)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        'NEWid',
+                        $queryBuilder->createNamedParameter($this->controller->new_unique_uid, \PDO::PARAM_INT)
+                    )
+                )
+                ->execute()
+                ->fetch();
+            if (is_array($sys_log_row)) {
+                $edit_record = $sys_log_row['tablename'] . ':' . $sys_log_row['recuid'];
+            }
+        }
+        $edit_record = $this->makeMenu($edit_record);
+        // Splitting the edit-record cmd value into table/uid:
+        $this->eRParts = explode(':', $edit_record);
+        $tableName = $this->eRParts[0];
+        // Delete-button flag?
+        $this->deleteButton = MathUtility::canBeInterpretedAsInteger($this->eRParts[1]) && $edit_record && ($tableName !== 'pages' && $this->controller->EDIT_CONTENT || $tableName === 'pages' && $this->controller->CALC_PERMS & Permission::PAGE_DELETE);
+        // If undo-button should be rendered (depends on available items in sys_history)
+        $this->undoButton = false;
+
+        // if there is no content on a page
+        // the parameter $this->eRParts[1] will be set to e.g. /new/1
+        // which is not an integer value and it will throw an exception here on certain dbms
+        // thus let's check that before as there cannot be a history for a new record
+        $this->undoButtonR = false;
+        if (MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_history');
+            $queryBuilder->getRestrictions()->removeAll();
+            $this->undoButtonR = $queryBuilder->select('tstamp')
+                ->from('sys_history')
+                ->where(
+                    $queryBuilder->expr()->eq(
+                        'tablename',
+                        $queryBuilder->createNamedParameter($tableName, \PDO::PARAM_STR)
+                    ),
+                    $queryBuilder->expr()->eq(
+                        'recuid',
+                        $queryBuilder->createNamedParameter($this->eRParts[1], \PDO::PARAM_INT)
+                    )
+                )
+                ->orderBy('tstamp', 'DESC')
+                ->setMaxResults(1)
+                ->execute()
+                ->fetch();
+        }
+        if ($this->undoButtonR) {
+            $this->undoButton = true;
+        }
+        // Setting up the Return URL for coming back to THIS script (if links take the user to another script)
+        $R_URL_parts = parse_url(GeneralUtility::getIndpEnv('REQUEST_URI'));
+        $R_URL_getvars = GeneralUtility::_GET();
+        unset($R_URL_getvars['popView']);
+        unset($R_URL_getvars['new_unique_uid']);
+        $R_URL_getvars['edit_record'] = $edit_record;
+        $this->R_URI = $R_URL_parts['path'] . '?' . GeneralUtility::implodeArrayForUrl('', $R_URL_getvars);
+
+        // Creating editing form:
+        if ($edit_record) {
+            // Splitting uid parts for special features, if new:
+            list($uidVal, $neighborRecordUid, $ex_colPos) = explode('/', $this->eRParts[1]);
+
+            if ($uidVal === 'new') {
+                $command = 'new';
+                // Page id of this new record
+                $theUid = $this->controller->id;
+                if ($neighborRecordUid) {
+                    $theUid = $neighborRecordUid;
+                }
+            } else {
+                $command = 'edit';
+                $theUid = $uidVal;
+                // Convert $uidVal to workspace version if any:
+                $draftRecord = BackendUtility::getWorkspaceVersionOfRecord($beUser->workspace, $tableName, $theUid, 'uid');
+                if ($draftRecord) {
+                    $theUid = $draftRecord['uid'];
+                }
+            }
+
+            // @todo: Hack because DatabaseInitializeNewRow reads from _GP directly
+            $GLOBALS['_GET']['defVals'][$tableName] = [
+                'colPos' => (int)$ex_colPos,
+                'sys_language_uid' => (int)$this->controller->current_sys_language
+            ];
+
+            /** @var TcaDatabaseRecord $formDataGroup */
+            $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
+            /** @var FormDataCompiler $formDataCompiler */
+            $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
+            /** @var NodeFactory $nodeFactory */
+            $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
+
+            try {
+                $formDataCompilerInput = [
+                    'tableName' => $tableName,
+                    'vanillaUid' => (int)$theUid,
+                    'command' => $command,
+                ];
+                $formData = $formDataCompiler->compile($formDataCompilerInput);
+
+                if ($command !== 'new') {
+                    BackendUtility::lockRecords($tableName, $formData['databaseRow']['uid'], $tableName === 'tt_content' ? $formData['databaseRow']['pid'] : 0);
+                }
+
+                $formData['renderType'] = 'outerWrapContainer';
+                $formResult = $nodeFactory->create($formData)->render();
+
+                $panel = $formResult['html'];
+                $formResult['html'] = '';
+
+                /** @var FormResultCompiler $formResultCompiler */
+                $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
+                $formResultCompiler->mergeResult($formResult);
+
+                $row = $formData['databaseRow'];
+                $new_unique_uid = '';
+                if ($command === 'new') {
+                    $new_unique_uid = $row['uid'];
+                }
+
+                // Add hidden fields:
+                if ($uidVal == 'new') {
+                    $panel .= '<input type="hidden" name="data[' . $tableName . '][' . $row['uid'] . '][pid]" value="' . $row['pid'] . '" />';
+                }
+                $redirect = ($uidVal == 'new' ? BackendUtility::getModuleUrl(
+                    $this->moduleName,
+                    ['id' => $this->controller->id, 'new_unique_uid' => $new_unique_uid, 'returnUrl' => $this->returnUrl]
+                ) : $this->R_URI);
+                $panel .= '
+                    <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />
+                    <input type="hidden" name="edit_record" value="' . $edit_record . '" />
+                    <input type="hidden" name="redirect" value="' . htmlspecialchars($redirect) . '" />
+                    ';
+                // Add JavaScript as needed around the form:
+                $content = $formResultCompiler->addCssFiles() . $panel . $formResultCompiler->printNeededJSFunctions();
+
+                // Display "is-locked" message:
+                if ($command === 'edit') {
+                    $lockInfo = BackendUtility::isRecordLocked($tableName, $formData['databaseRow']['uid']);
+                    if ($lockInfo) {
+                        /** @var \TYPO3\CMS\Core\Messaging\FlashMessage $flashMessage */
+                        $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $lockInfo['msg'], '', FlashMessage::WARNING);
+                        /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
+                        $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
+                        /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
+                        $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
+                        $defaultFlashMessageQueue->enqueue($flashMessage);
+                    }
+                }
+            } catch (AccessDeniedException $e) {
+                // If no edit access, print error message:
+                $content = '<h2>' . htmlspecialchars($lang->getLL('noAccess')) . '</h2>';
+                $content .= '<div>' . $lang->getLL('noAccess_msg') . '<br /><br />' . ($beUser->errorMsg ? 'Reason: ' . $beUser->errorMsg . '<br /><br />' : '') . '</div>';
+            }
+        } else {
+            // If no edit access, print error message:
+            $content = '<h2>' . $lang->getLL('noAccess') . '</h2>';
+            $content .= '<div>' . $lang->getLL('noAccess_msg') . '</div>';
+        }
+
+        // Element selection matrix:
+        if ($tableName === 'tt_content' && MathUtility::canBeInterpretedAsInteger($this->eRParts[1])) {
+            $content .= '<h2>' . $lang->getLL('CEonThisPage') . '</h2>';
+            // PositionMap
+            $posMap = GeneralUtility::makeInstance(ContentLayoutPagePositionMap::class);
+            $posMap->cur_sys_language = $this->controller->current_sys_language;
+            $content .= $posMap->printContentElementColumns(
+                $this->controller->id,
+                $this->eRParts[1],
+                $this->controller->colPosList,
+                $this->controller->MOD_SETTINGS['tt_content_showHidden'],
+                $this->R_URI
+                );
+            // Toggle hidden ContentElements
+            $numberOfHiddenElements = $this->controller->getNumberOfHiddenElements();
+            if ($numberOfHiddenElements) {
+                $content .= '<div class="checkbox">';
+                $content .= '<label for="checkTt_content_showHidden">';
+                $content .= BackendUtility::getFuncCheck($this->controller->id, 'SET[tt_content_showHidden]', $this->controller->MOD_SETTINGS['tt_content_showHidden'], '', '', 'id="checkTt_content_showHidden"');
+                $content .= (!$numberOfHiddenElements ? ('<span class="text-muted">' . htmlspecialchars($lang->getLL('hiddenCE')) . '</span>') : htmlspecialchars($lang->getLL('hiddenCE')) . ' (' . $numberOfHiddenElements . ')');
+                $content .= '</label>';
+                $content .= '</div>';
+            }
+            // CSH
+            $content .= BackendUtility::cshItem($this->descrTable, 'quickEdit_selElement', null, '<span class="btn btn-default btn-sm">|</span>');
+        }
+
+        $content = '<form action="' .
+            htmlspecialchars(BackendUtility::getModuleUrl('tce_db', ['prErr' => 1, 'uPT' => 1])) .
+            '" method="post" enctype="multipart/form-data" name="editform" id="PageLayoutController" onsubmit="return TBE_EDITOR.checkSubmit(1);">' .
+            $content .
+            '</form>';
+
+        return $content;
+    }
+
+    /**
+     * Returns LanguageService
+     *
+     * @return \TYPO3\CMS\Lang\LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'];
+    }
+
+    /**
+     * Returns the current BE user.
+     *
+     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
+     */
+    protected function getBackendUser()
+    {
+        return $GLOBALS['BE_USER'];
+    }
+}
index 3a62129..2b4cd36 100644 (file)
@@ -14,6 +14,7 @@ $EM_CONF[$_EXTKEY] = [
     'constraints' => [
         'depends' => [
             'typo3' => '8.6.0-8.6.99',
+            'backend' => '8.6.0-8.6.99',
             'indexed_search' => '8.6.0-8.6.99',
         ],
         'conflicts' => [
index c5d7676..0f123a4 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+
 defined('TYPO3_MODE') or die();
 
 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('indexed_search')) {
@@ -26,3 +27,10 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typolinkProcessing']['typolinkModifyP
 
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['fetchPageId-PostProcessing']['compatibility7_urlscheme']
     = \TYPO3\CMS\Compatibility7\Hooks\EnforceUrlSchemeHook::class . '->redirectIfUrlSchemeDoesNotMatch';
+
+// Enable action `QuickEdit` in page layout controller again
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Backend\Controller\PageLayoutController::class]['initActionHook']['compatibility7_quickedit']
+    = \TYPO3\CMS\Compatibility7\Hooks\PageLayoutActionHook::class . '->initAction';
+
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Backend\Controller\PageLayoutController::class]['renderActionHook']['compatibility7_quickedit']
+    = \TYPO3\CMS\Compatibility7\Hooks\PageLayoutActionHook::class . '->renderAction';
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-79364-MovePageModuleFunctionQuickEditToCompatibility7.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-79364-MovePageModuleFunctionQuickEditToCompatibility7.rst
new file mode 100644 (file)
index 0000000..74b4429
--- /dev/null
@@ -0,0 +1,27 @@
+.. include:: ../../Includes.txt
+
+==========================================================================
+Breaking: #79364 - Move page module function `QuickEdit` to compatibility7
+==========================================================================
+
+See :issue:`79364`
+
+Description
+===========
+
+The function `QuickEdit` in the page module has been moved to EXT:compatibility7 and will not be developed further. EXT:compatibility7 will be moved to TER before the release of 8 LTS.
+
+
+Impact
+======
+
+Installation of EXT:compatibility7 is required to continue using the `QuickEdit` function of the page module.
+
+
+Affected Installations
+======================
+
+All installations depend on the `QuickEdit` function in the page module.
+
+
+.. index:: Backend
\ No newline at end of file
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-79364-DeprecateMembersInPageLayoutController.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-79364-DeprecateMembersInPageLayoutController.rst
new file mode 100644 (file)
index 0000000..1d6b80f
--- /dev/null
@@ -0,0 +1,26 @@
+.. include:: ../../Includes.txt
+
+===============================================================
+Deprecation: #79364 - Deprecate members in PageLayoutController
+===============================================================
+
+See :issue:`79364`
+
+Description
+===========
+
+Deprecate the members :php:`\TYPO3\CMS\Backend\Controller\PageLayoutController::edit_record` and :php:`\TYPO3\CMS\Backend\Controller\PageLayoutController::new_unique_uid`.
+
+
+Impact
+======
+
+Installation of EXT:compatibility7 is required to continue using this members until they are removed in TYPO3 CMS 9.
+
+
+Affected Installations
+======================
+
+Any installation using the mentioned members :php:`\TYPO3\CMS\Backend\Controller\PageLayoutController::edit_record` and :php:`\TYPO3\CMS\Backend\Controller\PageLayoutController::new_unique_uid`.
+
+.. index:: PHP-API
\ No newline at end of file