[BUGFIX] Hide save and new button in connected translation mode 05/56705/4
authorPatrick Broens <patrick@patrickbroens.nl>
Mon, 16 Apr 2018 18:27:45 +0000 (20:27 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Tue, 17 Apr 2018 20:04:37 +0000 (22:04 +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/56705
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Mathias Schreiber <mathias.schreiber@typo3.com>
Tested-by: Mathias Schreiber <mathias.schreiber@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 099237b..eaa06bc 100644 (file)
@@ -30,6 +30,7 @@ use TYPO3\CMS\Backend\Template\ModuleTemplate;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait;
 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;
@@ -1361,6 +1362,23 @@ class EditDocumentController
         $lang = $this->getLanguageService();
         /** @var UriBuilder $uriBuilder */
         $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+
+        $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.
         $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
@@ -1408,8 +1426,22 @@ class EditDocumentController
                     $saveSplitButton->addItem($saveAndOpenButton);
                 }
             }
+
             // SAVE / NEW button:
-            if (count($this->elementsData) === 1 && !empty($this->firstEl['table']) && $this->getTsConfigOption($this->firstEl['table'], 'saveDocNew')) {
+            $showSaveAndNewButton = (
+                count($this->elementsData) === 1
+                && !empty($this->firstEl['table'])
+                && $this->getTsConfigOption($this->firstEl['table'], 'saveDocNew')
+            );
+            // 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')
@@ -1470,14 +1502,9 @@ class EditDocumentController
             ));
         $buttonBar->addButton($closeButton);
         // DUPLICATE button:
-        $record = BackendUtility::getRecord($this->firstEl['table'], $this->firstEl['uid']);
-        $TCActrl = $GLOBALS['TCA'][$this->firstEl['table']]['ctrl'];
         $l18nParent = isset($TCActrl['transOrigPointerField'], $record[$TCActrl['transOrigPointerField']])
             ? (int)$record[$TCActrl['transOrigPointerField']]
             : 0;
-        $sysLanguageUid = isset($TCActrl['languageField'], $record[$TCActrl['languageField']])
-            ? (int)$record[$TCActrl['languageField']]
-            : 0;
         $showDuplicateButton = false;
         if (
             $this->firstEl['cmd'] !== 'new'
@@ -1671,6 +1698,111 @@ class EditDocumentController
     }
 
     /**
+     * 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.