[BUGFIX] Hide save and new button in connected translation mode 17/56817/2
authorPatrick Broens <patrick@patrickbroens.nl>
Mon, 16 Apr 2018 18:27:45 +0000 (20:27 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Thu, 26 Apr 2018 09:13:26 +0000 (11:13 +0200)
In connected translation mode it should not be possible to use the
save and new button as this would lead to an inconsistent translation
state. This change adds an additional condition for tt_content records
to determine if the content is in free translation mode. Only in free
translation mode the save and new is shown.

Resolves: #84752
Releases: master, 8.7
Change-Id: Id500098ef9f642472e96cce59205b4a25377e421
Reviewed-on: https://review.typo3.org/56817
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
typo3/sysext/backend/Classes/Controller/EditDocumentController.php

index a9905d6..aa54917 100644 (file)
@@ -27,6 +27,7 @@ use TYPO3\CMS\Backend\Module\AbstractModule;
 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Query\QueryBuilder;
 use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
@@ -1157,6 +1158,22 @@ class EditDocumentController extends AbstractModule
     protected function getButtons()
     {
         $lang = $this->getLanguageService();
+        $isSavedRecord = (
+            $this->firstEl['cmd'] !== 'new'
+            && MathUtility::canBeInterpretedAsInteger($this->firstEl['uid'])
+        );
+
+        $record = BackendUtility::getRecord($this->firstEl['table'], $this->firstEl['uid']);
+        $TCActrl = $GLOBALS['TCA'][$this->firstEl['table']]['ctrl'];
+
+        $sysLanguageUid = 0;
+        if ($isSavedRecord
+            && isset($TCActrl['languageField'], $record[$TCActrl['languageField']])) {
+            $sysLanguageUid = (int)$record[$TCActrl['languageField']];
+        } elseif (isset($this->defVals['sys_language_uid'])) {
+            $sysLanguageUid = (int)$this->defVals['sys_language_uid'];
+        }
+
         // Render SAVE type buttons:
         // The action of each button is decided by its name attribute. (See doProcessData())
         $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
@@ -1204,8 +1221,21 @@ class EditDocumentController extends AbstractModule
                     $saveSplitButton->addItem($saveAndOpenButton);
                 }
             }
+
             // SAVE / NEW button:
-            if (count($this->elementsData) === 1 && $this->getNewIconMode($this->firstEl['table'])) {
+            $showSaveAndNewButton = (
+                count($this->elementsData) === 1
+                && $this->getNewIconMode($this->firstEl['table'])
+            );
+            // Hide the button for tt_content when in connected translation mode
+            if ($this->firstEl['table'] === 'tt_content') {
+                $showSaveAndNewButton = $this->isPageInFreeTranslationMode(
+                    (int)$this->pageinfo['uid'],
+                    !$isSavedRecord ? (int)$this->defVals['colPos'] : (int)$record['colPos'],
+                    $sysLanguageUid
+                );
+            }
+            if ($showSaveAndNewButton) {
                 $saveAndNewButton = $buttonBar->makeInputButton()
                     ->setName('_savedoknew')
                     ->setClasses('t3js-editform-submitButton')
@@ -1265,6 +1295,7 @@ class EditDocumentController extends AbstractModule
                 Icon::SIZE_SMALL
             ));
         $buttonBar->addButton($closeButton);
+
         // DELETE + UNDO buttons:
         if (!$this->errorC
             && !$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly']
@@ -1399,6 +1430,111 @@ class EditDocumentController extends AbstractModule
     }
 
     /**
+     * Check if the page is in free translation mode
+     *
+     * @param int $page
+     * @param int $column
+     * @param int $language
+     * @return bool
+     */
+    protected function isPageInFreeTranslationMode(int $page, int $column, int $language): bool
+    {
+        $freeTranslationMode = false;
+
+        if ($this->getConnectedContentElementTranslationsCount($page, $column, $language) === 0
+            && $this->getStandAloneContentElementTranslationsCount($page, $column, $language) >= 0) {
+            $freeTranslationMode = true;
+        }
+
+        return $freeTranslationMode;
+    }
+
+    /**
+     * Get the count of connected translated content elements
+     *
+     * @param int $page
+     * @param int $column
+     * @param int $language
+     * @return int
+     */
+    protected function getConnectedContentElementTranslationsCount(int $page, int $column, int $language): int
+    {
+        $queryBuilder = $this->getQueryBuilderForTranslationMode($page, $column, $language);
+
+        return (int)$queryBuilder
+            ->andWhere(
+                $queryBuilder->expr()->gt(
+                    $GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField'],
+                    $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+                )
+            )
+            ->execute()
+            ->fetchColumn(0);
+    }
+
+    /**
+     * Get the count of standalone translated content elements
+     *
+     * @param int $page
+     * @param int $column
+     * @param int $language
+     * @return int
+     */
+    protected function getStandAloneContentElementTranslationsCount(int $page, int $column, int $language): int
+    {
+        $queryBuilder = $this->getQueryBuilderForTranslationMode($page, $column, $language);
+
+        return (int)$queryBuilder
+            ->andWhere(
+                $queryBuilder->expr()->eq(
+                    $GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField'],
+                    $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+                )
+            )
+            ->execute()
+            ->fetchColumn(0);
+    }
+
+    /**
+     * Get the query builder for the translation mode
+     *
+     * @param int $page
+     * @param int $column
+     * @param int $language
+     * @return QueryBuilder
+     */
+    protected function getQueryBuilderForTranslationMode(int $page, int $column, int $language): QueryBuilder
+    {
+        $languageField = $GLOBALS['TCA']['tt_content']['ctrl']['languageField'];
+
+        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getQueryBuilderForTable('tt_content');
+
+        $queryBuilder->getRestrictions()
+            ->removeAll()
+            ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
+            ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
+
+        return $queryBuilder
+            ->count('uid')
+            ->from('tt_content')
+            ->where(
+                $queryBuilder->expr()->eq(
+                    'pid',
+                    $queryBuilder->createNamedParameter($page, \PDO::PARAM_INT)
+                ),
+                $queryBuilder->expr()->eq(
+                    $languageField,
+                    $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
+                ),
+                $queryBuilder->expr()->eq(
+                    'colPos',
+                    $queryBuilder->createNamedParameter($column, \PDO::PARAM_INT)
+                )
+            );
+    }
+
+    /**
      * Put together the various elements (buttons, selectors, form) into a table
      *
      * @param string $editForm HTML form.