diff --git a/typo3/sysext/backend/Classes/Clipboard/Clipboard.php b/typo3/sysext/backend/Classes/Clipboard/Clipboard.php index a763d570188e886db1de03eca678f8f7f074075c..82c51d746cccae9163f12b80c0754da3b5dafc97 100644 --- a/typo3/sysext/backend/Classes/Clipboard/Clipboard.php +++ b/typo3/sysext/backend/Classes/Clipboard/Clipboard.php @@ -474,7 +474,7 @@ class Clipboard { $lines = []; $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; - if ($table !== 'pages' && BackendUtility::isTableLocalizable($table) && $table !== 'pages_language_overlay') { + if (BackendUtility::isTableLocalizable($table)) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $queryBuilder->getRestrictions() ->removeAll() diff --git a/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php b/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php index fdf659285ef3059663ecf4d357cde7376b2b490f..972793705ce011f478fd256ab75e233eed682633 100644 --- a/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php +++ b/typo3/sysext/backend/Classes/Configuration/TranslationConfigurationProvider.php @@ -110,37 +110,36 @@ class TranslationConfigurationProvider if (!is_array($row)) { return 'Record "' . $table . '_' . $uid . '" was not found'; } - $translationTable = $this->getTranslationTable($table); - if ($translationTable === '') { + if (!BackendUtility::isTableLocalizable($table)) { return 'Translation is not supported for this table!'; } - if ($translationTable === $table && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) { + if ($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) { return 'Record "' . $table . '_' . $uid . '" seems to be a translation already (has a language value "' . $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] . '", relation to record "' . $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] . '")'; } - if ($translationTable === $table && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { + if ($row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) { return 'Record "' . $table . '_' . $uid . '" seems to be a translation already (has a relation to record "' . $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] . '")'; } // Look for translations of this record, index by language field value: if (!$selFieldList) { - $selFieldList = 'uid,' . $GLOBALS['TCA'][$translationTable]['ctrl']['languageField']; + $selFieldList = 'uid,' . $GLOBALS['TCA'][$table]['ctrl']['languageField']; } - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($translationTable); + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $queryBuilder ->select(...GeneralUtility::trimExplode(',', $selFieldList)) - ->from($translationTable) + ->from($table) ->where( $queryBuilder->expr()->eq( - $GLOBALS['TCA'][$translationTable]['ctrl']['transOrigPointerField'], + $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'], $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( 'pid', $queryBuilder->createNamedParameter( - ($table === 'pages' ? $row['uid'] : $row['pid']), + $row['pid'], \PDO::PARAM_INT ) ) @@ -148,7 +147,7 @@ class TranslationConfigurationProvider if (!$languageUid) { $queryBuilder->andWhere( $queryBuilder->expr()->gt( - $GLOBALS['TCA'][$translationTable]['ctrl']['languageField'], + $GLOBALS['TCA'][$table]['ctrl']['languageField'], $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) ) ); @@ -156,7 +155,7 @@ class TranslationConfigurationProvider $queryBuilder ->andWhere( $queryBuilder->expr()->eq( - $GLOBALS['TCA'][$translationTable]['ctrl']['languageField'], + $GLOBALS['TCA'][$table]['ctrl']['languageField'], $queryBuilder->createNamedParameter($languageUid, \PDO::PARAM_INT) ) ); @@ -168,10 +167,10 @@ class TranslationConfigurationProvider $translations = []; $translationsErrors = []; foreach ($translationRecords as $translationRecord) { - if (!isset($translations[$translationRecord[$GLOBALS['TCA'][$translationTable]['ctrl']['languageField']]])) { - $translations[$translationRecord[$GLOBALS['TCA'][$translationTable]['ctrl']['languageField']]] = $translationRecord; + if (!isset($translations[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]])) { + $translations[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]] = $translationRecord; } else { - $translationsErrors[$translationRecord[$GLOBALS['TCA'][$translationTable]['ctrl']['languageField']]][] = $translationRecord; + $translationsErrors[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]][] = $translationRecord; } } return [ @@ -179,7 +178,6 @@ class TranslationConfigurationProvider 'uid' => $uid, 'CType' => $row['CType'], 'sys_language_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']], - 'translation_table' => $translationTable, 'translations' => $translations, 'excessive_translations' => $translationsErrors ]; @@ -190,10 +188,12 @@ class TranslationConfigurationProvider * * @param string $table The table name * @return string + * @deprecated since TYPO3 v9, will be removed in TYPO3 v10 as foreign translation table is not supported anymore */ public function getTranslationTable($table) { - return $this->isTranslationInOwnTable($table) ? $table : $this->foreignTranslationTable($table); + trigger_error('getTranslationTable() will be removed in TYPO3 v10, as the translation table is always the same as the original table.', E_USER_DEPRECATED); + return BackendUtility::isTableLocalizable($table) ? $table : ''; } /** @@ -201,21 +201,27 @@ class TranslationConfigurationProvider * * @param string $table The table name * @return bool + * @deprecated since TYPO3 v9, will be removed in TYPO3 v10 as foreign translation table is not supported anymore */ public function isTranslationInOwnTable($table) { - return $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && $table !== 'pages_language_overlay'; + trigger_error('isTranslationInOwnTable() will be removed in TYPO3 v10, as the translation table is always the same as the original table.', E_USER_DEPRECATED); + return $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; } /** - * Returns foreign translation table, if any + * Returns foreign translation table, if any. + * Since TYPO3 v9, even "pages" translations are stored in the same table, having this method return always + * empty, as with other tables as well. * * @param string $table The table name * @return string Translation foreign table + * @deprecated since TYPO3 v9, will be removed in TYPO3 v10 as foreign translation table is not supported anymore */ public function foreignTranslationTable($table) { - return $table === 'pages' ? 'pages_language_overlay' : ''; + trigger_error('foreignTranslationTable() will be removed in TYPO3 v10, as the translation table is always the same as the original table.', E_USER_DEPRECATED); + return ''; } /** diff --git a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php index 07dcc08875ae5102b2ea2fde608a447d9cd48b55..c3ea94e0819a72a58971de7d49a829684c771f6f 100644 --- a/typo3/sysext/backend/Classes/Controller/EditDocumentController.php +++ b/typo3/sysext/backend/Classes/Controller/EditDocumentController.php @@ -1509,14 +1509,20 @@ class EditDocumentController if ($this->getBackendUser()->check('tables_modify', $table) && $languageField && $transOrigPointerField - && $table !== 'pages_language_overlay' ) { if (is_null($pid)) { $row = BackendUtility::getRecord($table, $uid, 'pid'); $pid = $row['pid']; } // Get all available languages for the page - $langRows = $this->getLanguages($pid); + // If editing a page, the translations of the current UID need to be fetched + if ($table === 'pages') { + $row = BackendUtility::getRecord($table, $uid, 'l10n_parent'); + // Ensure the check is always done against the default language page + $langRows = $this->getLanguages($row['l10n_parent'] ?: $uid); + } else { + $langRows = $this->getLanguages($pid); + } // Page available in other languages than default language? if (is_array($langRows) && count($langRows) > 1) { $rowsByLang = []; @@ -1631,7 +1637,6 @@ class EditDocumentController public function localizationRedirect($justLocalized) { list($table, $origUid, $language) = explode(':', $justLocalized); - $table = $table === 'pages' ? 'pages_language_overlay' : $table; if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] @@ -1674,7 +1679,7 @@ class EditDocumentController * * @param int $id Page id: If zero, the query will select all sys_language records from root level which are NOT * hidden. If set to another value, the query will select all sys_language records that has a - * pages_language_overlay record on that page (and is not hidden, unless you are admin user) + * translation record on that page (and is not hidden, unless you are admin user) * @return array Language records including faked record for default language */ public function getLanguages($id) @@ -1718,11 +1723,11 @@ class EditDocumentController $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(HiddenRestriction::class)); } - // Add join with pages_languages_overlay table to only show active languages - $queryBuilder->from('pages_language_overlay', 'o') + // Add join with pages translations to only show active languages + $queryBuilder->from('pages', 'o') ->where( $queryBuilder->expr()->eq('o.sys_language_uid', $queryBuilder->quoteIdentifier('s.uid')), - $queryBuilder->expr()->eq('o.pid', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)) + $queryBuilder->expr()->eq('o.l10n_parent', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT)) ); } diff --git a/typo3/sysext/backend/Classes/Controller/NewRecordController.php b/typo3/sysext/backend/Classes/Controller/NewRecordController.php index f1925e9fa00949870478fe63ccc194e5e384c3d9..5e15f40e3d30f2a8eb85a430bccde06483573354 100644 --- a/typo3/sysext/backend/Classes/Controller/NewRecordController.php +++ b/typo3/sysext/backend/Classes/Controller/NewRecordController.php @@ -557,9 +557,6 @@ class NewRecordController $iconFile[$_EXTKEY] = ''; } } else { - if ($table === 'pages_language_overlay' && !$this->checkIfLanguagesExist()) { - continue; - } $_EXTKEY = 'system'; $thisTitle = $lang->getLL('system_records'); $iconFile['system'] = $this->moduleTemplate->getIconFactory()->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render(); @@ -656,8 +653,8 @@ class NewRecordController if ($table === 'pages' && $addContentTable) { $urlParameters['tt_content']['prev'] = 'new'; $urlParameters['returnNewPageId'] = 1; - } elseif ($table === 'pages_language_overlay') { - $urlParameters['overrideVals']['pages_language_overlay']['doktype'] = (int)$this->pageinfo['doktype']; + } elseif ($table === 'pages') { + $urlParameters['overrideVals']['pages']['doktype'] = (int)$this->pageinfo['doktype']; } $url = BackendUtility::getModuleUrl('record_edit', $urlParameters); return '<a href="' . htmlspecialchars($url) . '">' . $linkText . '</a>'; diff --git a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php index d5d0e272c5bd3c2ec102755f0a77855d44fc345a..7c7b6560c5f3fdbe22ab631b80e02f4fd4648de8 100644 --- a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php +++ b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php @@ -306,7 +306,7 @@ class PageLayoutController $this->modSharedTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.SHARED'); $this->modTSconfig = BackendUtility::getModTSconfig($this->id, 'mod.' . $this->moduleName); - // First, select all pages_language_overlay records on the current page. Each represents a possibility for a language on the page. Add these to language selector. + // First, select all localized page records on the current page. Each represents a possibility for a language on the page. Add these to language selector. $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); $queryBuilder->getRestrictions()->removeAll(); if ($this->id) { @@ -314,38 +314,38 @@ class PageLayoutController ->from('sys_language') ->join( 'sys_language', - 'pages_language_overlay', - 'pages_language_overlay', + 'pages', + 'pages', $queryBuilder->expr()->eq( 'sys_language.uid', - $queryBuilder->quoteIdentifier('pages_language_overlay.sys_language_uid') + $queryBuilder->quoteIdentifier('pages.sys_language_uid') ) ) ->where( $queryBuilder->expr()->eq( - 'pages_language_overlay.deleted', + 'pages.deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( - 'pages_language_overlay.pid', + 'pages.l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT) ), $queryBuilder->expr()->orX( $queryBuilder->expr()->gte( - 'pages_language_overlay.t3ver_state', + 'pages.t3ver_state', $queryBuilder->createNamedParameter( (string)new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT ) ), $queryBuilder->expr()->eq( - 'pages_language_overlay.t3ver_wsid', + 'pages.t3ver_wsid', $queryBuilder->createNamedParameter($this->getBackendUser()->workspace, \PDO::PARAM_INT) ) ) ) ->groupBy( - 'pages_language_overlay.sys_language_uid', + 'pages.sys_language_uid', 'sys_language.uid', 'sys_language.pid', 'sys_language.tstamp', @@ -634,16 +634,19 @@ class PageLayoutController { if ($this->current_sys_language > 0) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); - $overlayRecord = $queryBuilder + $localizedPage = $queryBuilder ->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq( + 'l10n_parent', + $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT) + ), $queryBuilder->expr()->eq( 'sys_language_uid', $queryBuilder->createNamedParameter($this->current_sys_language, \PDO::PARAM_INT) @@ -652,8 +655,8 @@ class PageLayoutController ->setMaxResults(1) ->execute() ->fetch(); - BackendUtility::workspaceOL('pages_language_overlay', $overlayRecord); - return $overlayRecord['title']; + BackendUtility::workspaceOL('pages', $localizedPage); + return $localizedPage['title']; } return $this->pageinfo['title']; } @@ -998,20 +1001,20 @@ class PageLayoutController if (!$this->modTSconfig['properties']['disableIconToolbar']) { // 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 + // Edit localized pages only when one specific language is selected if ($this->MOD_SETTINGS['function'] == 1 && $this->current_sys_language > 0) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $overlayRecord = $queryBuilder ->select('uid') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->eq( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( @@ -1025,7 +1028,7 @@ class PageLayoutController // Edit button $urlParameters = [ 'edit' => [ - 'pages_language_overlay' => [ + 'pages' => [ $overlayRecord['uid'] => 'edit' ] ], diff --git a/typo3/sysext/backend/Classes/Form/FormDataCompiler.php b/typo3/sysext/backend/Classes/Form/FormDataCompiler.php index 7f58166d70f3edfa99aa641d443563fe6089a1a7..e31c41369914f8fe9c9de5477e845352ce7e14f5 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataCompiler.php +++ b/typo3/sysext/backend/Classes/Form/FormDataCompiler.php @@ -155,6 +155,9 @@ class FormDataCompiler // Parent page record is either the full row of the parent page the record is located at or should // be added to, or it is NULL, if a record is added or edited below the root page node. 'parentPageRow' => null, + // If a translated page is handled, the page row of the default language (the page against all page checks + // are made) is set here + 'defaultLanguagePageRow' => null, // Holds the "neighbor" row if incoming vanillaUid is negative and record creation is relative to a row of the same table. 'neighborRow' => null, // For "new" this is the fully initialized row with defaults diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php index 1a96445b11d558bfd939c49491d4090232d09b10..ad41104ea1be005f43aabeea639a2e9525c28bf8 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/AbstractItemProvider.php @@ -655,8 +655,7 @@ abstract class AbstractItemProvider $table = $result['tableName']; $backendUser = $this->getBackendUser(); // Guard clause returns if not correct table and field or if user is admin - if ($table !== 'pages' && $table !== 'pages_language_overlay' - || $fieldName !== 'doktype' || $backendUser->isAdmin() + if ($table !== 'pages' || $fieldName !== 'doktype' || $backendUser->isAdmin() ) { return $items; } diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseDefaultLanguagePageRow.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseDefaultLanguagePageRow.php new file mode 100644 index 0000000000000000000000000000000000000000..48fd45bebeb6a90a7cd758b517363b86418266c7 --- /dev/null +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseDefaultLanguagePageRow.php @@ -0,0 +1,41 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Backend\Form\FormDataProvider; + +/* + * 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\Form\FormDataProviderInterface; + +/** + * Fetch page in default language from database if it's a translated pages record + */ +class DatabaseDefaultLanguagePageRow extends AbstractDatabaseRecordProvider implements FormDataProviderInterface +{ + /** + * Add default language page row of existing row to result + * defaultLanguagePageRow will stay NULL in result if a record is added or edited below root node + * + * @param array $result + * @return array + */ + public function addData(array $result) + { + // $defaultLanguagePageRow end up NULL if a record added or edited on root node + $tableName = $result['tableName']; + if ($tableName === 'pages' && $result['databaseRow'][$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0) { + $result['defaultLanguagePageRow'] = $this->getRecordFromDatabase('pages', $result['databaseRow'][$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']]); + } + return $result; + } +} diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php index 34f0ea48c4480ff78dc1287fe87aa2319c7c6319..31633dc7dcd83543596981a217f400defc992ac1 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php @@ -45,15 +45,9 @@ class DatabaseLanguageRows implements FormDataProviderInterface if (isset($result['databaseRow'][$languageField]) && $result['databaseRow'][$languageField] > 0 && isset($result['databaseRow'][$fieldWithUidOfDefaultRecord]) && $result['databaseRow'][$fieldWithUidOfDefaultRecord] > 0 ) { - // Table pages has its overlays in pages_language_overlay, this is accounted here - $tableNameWithDefaultRecords = $result['tableName']; - if ($tableNameWithDefaultRecords === 'pages_language_overlay') { - $tableNameWithDefaultRecords = 'pages'; - } - // Default language record of localized record $defaultLanguageRow = $this->getRecordWorkspaceOverlay( - $tableNameWithDefaultRecords, + $result['tableName'], (int)$result['databaseRow'][$fieldWithUidOfDefaultRecord] ); if (empty($defaultLanguageRow)) { @@ -90,7 +84,7 @@ class DatabaseLanguageRows implements FormDataProviderInterface continue; } $translationInfo = $translationProvider->translationInfo( - $tableNameWithDefaultRecords, + $result['tableName'], (int)$result['databaseRow'][$fieldWithUidOfDefaultRecord], $additionalLanguageUid ); diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabasePageLanguageOverlayRows.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabasePageLanguageOverlayRows.php index 80355249df2df1ec2939d5835b80ce59ba91b564..d2f793c75d0753a31135c338d9cd74e5e51cf68d 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabasePageLanguageOverlayRows.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabasePageLanguageOverlayRows.php @@ -52,15 +52,15 @@ class DatabasePageLanguageOverlayRows implements FormDataProviderInterface protected function getDatabaseRows(int $pid): array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $rows = $queryBuilder->select('*') - ->from('pages_language_overlay') - ->where($queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))) + ->from('pages') + ->where($queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT))) ->execute() ->fetchAll(); diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseUserPermissionCheck.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseUserPermissionCheck.php index 27d637951d92671f2e7be8fc4aee4bc201b879b8..467db33c56ac864ecbdedfd4fc8dff548ce9360d 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseUserPermissionCheck.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseUserPermissionCheck.php @@ -114,7 +114,7 @@ class DatabaseUserPermissionCheck implements FormDataProviderInterface // A page or a record on a page is edited if ($result['tableName'] === 'pages') { // A page record is edited, check edit rights of this record directly - $userPermissionOnPage = $backendUser->calcPerms($result['databaseRow']); + $userPermissionOnPage = $backendUser->calcPerms($result['defaultLanguagePageRow'] ?? $result['databaseRow']); if ((bool)($userPermissionOnPage & Permission::PAGE_EDIT) && $backendUser->check('pagetypes_select', $result['databaseRow'][$result['processedTca']['ctrl']['type']])) { $userHasAccess = true; } else { diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php index cf2b511b21989e6167c5bc6cfa2d1230159ae9a2..18401cfb68851beada69103c6aacd19aa4b52e90 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInline.php @@ -135,9 +135,6 @@ class TcaInline extends AbstractDatabaseRecordProvider implements FormDataProvid $result['databaseRow'][$fieldName] = implode(',', $connectedUidsOfLocalizedOverlay); if ($result['inlineCompileExistingChildren']) { $tableNameWithDefaultRecords = $result['tableName']; - if ($tableNameWithDefaultRecords === 'pages_language_overlay') { - $tableNameWithDefaultRecords = 'pages'; - } $connectedUidsOfDefaultLanguageRecord = $this->resolveConnectedRecordUids( $result['processedTca']['columns'][$fieldName]['config'], $tableNameWithDefaultRecords, diff --git a/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php b/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php index ef2e157646d105635108e5cc73a63a5f8b9310df..5bb83cc77379ab98c2c12d726d8f0516c24c195f 100644 --- a/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php +++ b/typo3/sysext/backend/Classes/RecordList/AbstractRecordList.php @@ -449,17 +449,17 @@ abstract class AbstractRecordList { // Look up page overlays: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder ->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->andX( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->gt('sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)) ) ) diff --git a/typo3/sysext/backend/Classes/Tree/Pagetree/DataProvider.php b/typo3/sysext/backend/Classes/Tree/Pagetree/DataProvider.php index 64d90fa1107cdc820f6a0cec619fd98211873ca2..5618bea16bac2d18f76ce6c920270739b944b601 100644 --- a/typo3/sysext/backend/Classes/Tree/Pagetree/DataProvider.php +++ b/typo3/sysext/backend/Classes/Tree/Pagetree/DataProvider.php @@ -444,6 +444,11 @@ class DataProvider extends \TYPO3\CMS\Backend\Tree\AbstractTreeDataProvider ); } + // Only show records in default language + $queryBuilder->andWhere( + $expressionBuilder->eq('sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)) + ); + if ($searchFilter !== '') { $searchParts = $expressionBuilder->orX(); if (is_numeric($searchFilter) && $searchFilter > 0) { diff --git a/typo3/sysext/backend/Classes/Tree/View/PageTreeView.php b/typo3/sysext/backend/Classes/Tree/View/PageTreeView.php index 35e4a504b835b44d037bbfff59336b39ed15f252..1a58a5856693d2baf60ece1aec960c92abdb973a 100644 --- a/typo3/sysext/backend/Classes/Tree/View/PageTreeView.php +++ b/typo3/sysext/backend/Classes/Tree/View/PageTreeView.php @@ -70,7 +70,7 @@ class PageTreeView extends AbstractTreeView */ public function init($clause = '', $orderByFields = '') { - parent::init(' AND deleted=0 ' . $clause, 'sorting'); + parent::init(' AND deleted=0 AND sys_language_uid=0 ' . $clause, 'sorting'); } /** diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index 1c11d1070f1565b3387f6e586db1a766f2886a33..3b70932c4c05436ac749edfc5d1bdead1c80e27f 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -302,11 +302,6 @@ class BackendUtility { $recordLocalization = false; - // Pages still stores translations in the pages_language_overlay table, all other tables store in themself - if ($table === 'pages') { - $table = 'pages_language_overlay'; - } - if (self::isTableLocalizable($table)) { $tcaCtrl = $GLOBALS['TCA'][$table]['ctrl']; @@ -546,16 +541,15 @@ class BackendUtility } /** - * Gets the original translation pointer table. - * That is now the same table, apart from pages_language_overlay - * where pages is the original. + * Gets the original translation pointer table, which is always the same table * * @param string $table Name of the table * @return string Pointer table (if any) */ public static function getOriginalTranslationTable($table) { - return $table === 'pages_language_overlay' ? 'pages' : $table; + trigger_error('Starting with TYPO3 v9, the translation table is always the same as the original table, because pages_language_overlay has been migrated into pages table.', E_USER_DEPRECATED); + return $table; } /** @@ -3691,10 +3685,8 @@ class BackendUtility public static function translationCount($table, $ref, $msg = '') { $count = null; - if ($table !== 'pages' - && $GLOBALS['TCA'][$table]['ctrl']['languageField'] + if ($GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] - && $table !== 'pages_language_overlay' ) { $queryBuilder = static::getQueryBuilderForTable($table); $queryBuilder->getRestrictions() diff --git a/typo3/sysext/backend/Classes/View/PageLayoutView.php b/typo3/sysext/backend/Classes/View/PageLayoutView.php index 7df137cb510970cdfe92e5108c205c438d6b1d1d..30bd1f711457c2a9668d647366820d31fc46a50e 100644 --- a/typo3/sysext/backend/Classes/View/PageLayoutView.php +++ b/typo3/sysext/backend/Classes/View/PageLayoutView.php @@ -850,36 +850,15 @@ class PageLayoutView implements LoggerAwareInterface $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal'); $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/Paste'); $userCanEditPage = $this->ext_CALC_PERMS & Permission::PAGE_EDIT && !empty($this->id) && ($backendUser->isAdmin() || (int)$this->pageinfo['editlock'] === 0); - if ($this->tt_contentConfig['languageColsPointer'] > 0) { - $userCanEditPage = $this->getBackendUser()->check('tables_modify', 'pages_language_overlay'); - } if ($userCanEditPage) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); - $queryBuilder->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); - - $queryBuilder->select('uid') - ->from('pages_language_overlay') - ->where( - $queryBuilder->expr()->eq( - 'pid', - $queryBuilder->createNamedParameter((int)$this->id, \PDO::PARAM_INT) - ), - $queryBuilder->expr()->eq( - 'sys_language_uid', - $queryBuilder->createNamedParameter( - $this->tt_contentConfig['sys_language_uid'], - \PDO::PARAM_INT - ) - ) - ) - ->setMaxResults(1); - - $languageOverlayId = (int)$queryBuilder->execute()->fetchColumn(0); - + $languageOverlayId = 0; + $pageLocalizationRecord = BackendUtility::getRecordLocalization('pages', $this->id, (int)$this->tt_contentConfig['sys_language_uid']); + if (is_array($pageLocalizationRecord)) { + $pageLocalizationRecord = reset($pageLocalizationRecord); + } + if (!empty($pageLocalizationRecord['uid'])) { + $languageOverlayId = $pageLocalizationRecord['uid']; + } $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', 'function(PageActions) { PageActions.setPageId(' . (int)$this->id . '); PageActions.setLanguageOverlayId(' . $languageOverlayId . '); @@ -1298,43 +1277,24 @@ class PageLayoutView implements LoggerAwareInterface } // Language overlay page header: if ($lP) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); - $queryBuilder->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); - - $lpRecord = $queryBuilder->select('*') - ->from('pages_language_overlay') - ->where( - $queryBuilder->expr()->eq( - 'pid', - $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) - ), - $queryBuilder->expr()->eq( - 'sys_language_uid', - $queryBuilder->createNamedParameter($lP, \PDO::PARAM_INT) - ) - ) - ->setMaxResults(1) - ->execute() - ->fetch(); - - BackendUtility::workspaceOL('pages_language_overlay', $lpRecord); + $pageLocalizationRecord = BackendUtility::getRecordLocalization('pages', $id, $lP); + if (is_array($pageLocalizationRecord)) { + $pageLocalizationRecord = reset($pageLocalizationRecord); + } + BackendUtility::workspaceOL('pages', $pageLocalizationRecord); $recordIcon = BackendUtility::wrapClickMenuOnIcon( - $this->iconFactory->getIconForRecord('pages_language_overlay', $lpRecord, Icon::SIZE_SMALL)->render(), - 'pages_language_overlay', - $lpRecord['uid'] + $this->iconFactory->getIconForRecord('pages', $pageLocalizationRecord, Icon::SIZE_SMALL)->render(), + 'pages', + $pageLocalizationRecord['uid'] ); $urlParameters = [ 'edit' => [ - 'pages_language_overlay' => [ - $lpRecord['uid'] => 'edit' + 'pages' => [ + $pageLocalizationRecord['uid'] => 'edit' ] ], 'overrideVals' => [ - 'pages_language_overlay' => [ + 'pages' => [ 'sys_language_uid' => $lP ] ], @@ -1342,7 +1302,7 @@ class PageLayoutView implements LoggerAwareInterface ]; $url = BackendUtility::getModuleUrl('record_edit', $urlParameters); $editLink = ( - $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') + $this->getBackendUser()->check('tables_modify', 'pages') ? '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"' . ' title="' . htmlspecialchars($this->getLanguageService()->getLL('edit')) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' @@ -1354,7 +1314,7 @@ class PageLayoutView implements LoggerAwareInterface . $viewLink . $editLink . '</div>' - . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($lpRecord['title'], 20)); + . ' ' . $recordIcon . ' ' . htmlspecialchars(GeneralUtility::fixed_lgd_cs($pageLocalizationRecord['title'], 20)); } else { $editLink = ''; $recordIcon = ''; @@ -1374,7 +1334,7 @@ class PageLayoutView implements LoggerAwareInterface ]; $url = BackendUtility::getModuleUrl('record_edit', $urlParameters); $editLink = ( - $this->getBackendUser()->check('tables_modify', 'pages_language_overlay') + $this->getBackendUser()->check('tables_modify', 'pages') ? '<a href="' . htmlspecialchars($url) . '" class="btn btn-default btn-sm"' . ' title="' . htmlspecialchars($this->getLanguageService()->getLL('edit')) . '">' . $this->iconFactory->getIcon('actions-open', Icon::SIZE_SMALL)->render() . '</a>' @@ -1693,6 +1653,7 @@ class PageLayoutView implements LoggerAwareInterface ->from('pages') ->where( $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)), $this->getBackendUser()->getPagePermsClause(1) ); @@ -2464,13 +2425,13 @@ class PageLayoutView implements LoggerAwareInterface * Displays only languages which are not yet present for the current page and * that are not disabled with page TS. * - * @param int $id Page id for which to create a new language (pages_language_overlay record) + * @param int $id Page id for which to create a new translation record of pages * @return string <select> HTML element (if there were items for the box anyways...) * @see getTable_tt_content() */ public function languageSelector($id) { - if ($this->getBackendUser()->check('tables_modify', 'pages_language_overlay')) { + if ($this->getBackendUser()->check('tables_modify', 'pages')) { // First, select all $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); $queryBuilder->getRestrictions()->removeAll(); @@ -2492,35 +2453,35 @@ class PageLayoutView implements LoggerAwareInterface ->from('sys_language') ->join( 'sys_language', - 'pages_language_overlay', - 'pages_language_overlay', - $queryBuilder->expr()->eq('sys_language.uid', $queryBuilder->quoteIdentifier('pages_language_overlay.sys_language_uid')) + 'pages', + 'pages', + $queryBuilder->expr()->eq('sys_language.uid', $queryBuilder->quoteIdentifier('pages.sys_language_uid')) ) ->where( $queryBuilder->expr()->eq( - 'pages_language_overlay.deleted', + 'pages.deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( - 'pages_language_overlay.pid', + 'pages.l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT) ), $queryBuilder->expr()->orX( $queryBuilder->expr()->gte( - 'pages_language_overlay.t3ver_state', + 'pages.t3ver_state', $queryBuilder->createNamedParameter( (string)new VersionState(VersionState::DEFAULT_STATE), \PDO::PARAM_INT ) ), $queryBuilder->expr()->eq( - 'pages_language_overlay.t3ver_wsid', + 'pages.t3ver_wsid', $queryBuilder->createNamedParameter($this->getBackendUser()->workspace, \PDO::PARAM_INT) ) ) ) ->groupBy( - 'pages_language_overlay.sys_language_uid', + 'pages.sys_language_uid', 'sys_language.uid', 'sys_language.pid', 'sys_language.tstamp', @@ -3399,9 +3360,7 @@ class PageLayoutView implements LoggerAwareInterface } // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set - if ( - $table !== 'pages_language_overlay' - && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) + if (!empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && (GeneralUtility::inList($this->hideTranslations, $table) || $this->hideTranslations === '*') ) { $queryBuilder->andWhere( @@ -4338,17 +4297,17 @@ class PageLayoutView implements LoggerAwareInterface { // Look up page overlays: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder ->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->andX( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->gt( 'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js index 7e4999a51a5852fb6f243e4e5b1da2ed7d903505..e0b40289649533e80d198e029c4350103ece478c 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js @@ -192,20 +192,17 @@ define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent'], function($, Persisten $field.attr('disabled', 'disabled'); var parameters = {}, - pagesTable, recordUid; if (PageActions.settings.language.pageOverlayId === 0) { - pagesTable = 'pages'; recordUid = PageActions.settings.pageId; } else { - pagesTable = 'pages_language_overlay'; recordUid = PageActions.settings.language.pageOverlayId; } parameters.data = {}; - parameters.data[pagesTable] = {}; - parameters.data[pagesTable][recordUid] = {title: $field.val()}; + parameters.data['pages'] = {}; + parameters.data['pages'][recordUid] = {title: $field.val()}; require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) { DataHandler.process(parameters).done(function() { diff --git a/typo3/sysext/backend/Tests/Functional/Controller/FormInlineAjaxControllerTest.php b/typo3/sysext/backend/Tests/Functional/Controller/FormInlineAjaxControllerTest.php index 5eaa829232a05368c608e78c82f4ee5b5f527365..0c06968624c08998f488ccfd778be3b37fdc3ce6 100644 --- a/typo3/sysext/backend/Tests/Functional/Controller/FormInlineAjaxControllerTest.php +++ b/typo3/sysext/backend/Tests/Functional/Controller/FormInlineAjaxControllerTest.php @@ -47,7 +47,6 @@ class FormInlineAjaxControllerTest extends FunctionalTestCase $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml'); $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/sys_language.xml'); - $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/core/Tests/Functional/Fixtures/pages_language_overlay.xml'); $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/backend/Tests/Functional/Fixtures/tx_irretutorial_1ncsv_hotel.xml'); $this->setUpBackendUserFromFixture(1); diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseDefaultLanguagePageRowTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseDefaultLanguagePageRowTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ec02c4d3e7421344ceb10ef470cc66b8d328017c --- /dev/null +++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseDefaultLanguagePageRowTest.php @@ -0,0 +1,103 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider; + +/* + * 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\Form\FormDataProvider\DatabaseDefaultLanguagePageRow; + +/** + * Test case + */ +class DatabaseDefaultLanguagePageRowTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase +{ + /** + * @var DatabaseDefaultLanguagePageRow|\PHPUnit_Framework_MockObject_MockObject + */ + protected $subject; + + protected function setUp() + { + $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] = 'l10n_parent'; + $this->subject = $this->getMockBuilder(DatabaseDefaultLanguagePageRow::class) + ->setMethods(['getDatabaseRow']) + ->getMock(); + } + + /** + * @test + */ + public function addDataDoesNotApplyToAnyNonPagesTable() + { + $input = [ + 'tableName' => 'tx_doandroidsdreamofelectricsheep', + 'databaseRow' => [ + 'uid' => 23, + 'l10n_parent' => 13, + 'sys_language_uid' => 23 + ] + ]; + $result = $this->subject->addData($input); + + $this->assertNull($result['defaultLanguagePageRow']); + } + + /** + * @test + */ + public function addDataDoesApplyToAPagesTableButNoChangeForDefaultLanguage() + { + $input = [ + 'tableName' => 'pages', + 'databaseRow' => [ + 'uid' => 23, + 'l10n_parent' => 0, + 'sys_language_uid' => 0 + ] + ]; + $result = $this->subject->addData($input); + $this->assertSame($input, $result); + } + + /** + * @test + */ + public function addDataDoesApplyToATranslatedPagesTable() + { + $input = [ + 'tableName' => 'pages', + 'databaseRow' => [ + 'uid' => 23, + 'pid' => 1, + 'l10n_parent' => 13, + 'sys_language_uid' => 8 + ] + ]; + + $defaultLanguagePageRow = [ + 'uid' => 13, + 'pid' => 1, + 'sys_language_uid' => 0, + 'l10n_parent' => 0 + ]; + + $this->subject->expects($this->once()) + ->method('getDatabaseRow') + ->with($input['tableName'], 13) + ->willReturn($defaultLanguagePageRow); + + $result = $this->subject->addData($input); + $this->assertEquals($defaultLanguagePageRow, $result['defaultLanguagePageRow']); + } +} diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php index c6d716a022e68010347500271e52e3f7fb76e2d1..d1810f02392bf18a989ec7bba4626f734e78b189 100644 --- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php @@ -579,7 +579,8 @@ class BackendUserAuthentication extends AbstractUserAuthentication return Permission::ALL; } // Return 0 if page is not within the allowed web mount - if (!$this->isInWebMount($row['uid'])) { + // Always do this for the default language page record + if (!$this->isInWebMount($row['l10n_parent'] ?: $row['uid'])) { return Permission::NOTHING; } $out = Permission::NOTHING; @@ -731,25 +732,16 @@ class BackendUserAuthentication extends AbstractUserAuthentication public function checkFullLanguagesAccess($table, $record) { $recordLocalizationAccess = $this->checkLanguageAccess(0); - if ($recordLocalizationAccess && (BackendUtility::isTableLocalizable($table) || $table === 'pages')) { - if ($table === 'pages') { - $l10nTable = 'pages_language_overlay'; - $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField']; - $pointerValue = $record['uid']; - } else { - $l10nTable = $table; - $pointerField = $GLOBALS['TCA'][$l10nTable]['ctrl']['transOrigPointerField']; - $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid']; - } - - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($l10nTable); + if ($recordLocalizationAccess && BackendUtility::isTableLocalizable($table)) { + $pointerField = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; + $pointerValue = $record[$pointerField] > 0 ? $record[$pointerField] : $record['uid']; + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); - $recordLocalization = $queryBuilder->select('*') - ->from($l10nTable) + ->from($table) ->where( $queryBuilder->expr()->eq( $pointerField, @@ -762,7 +754,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication if (is_array($recordLocalization)) { $languageAccess = $this->checkLanguageAccess( - $recordLocalization[$GLOBALS['TCA'][$l10nTable]['ctrl']['languageField']] + $recordLocalization[$GLOBALS['TCA'][$table]['ctrl']['languageField']] ); $recordLocalizationAccess = $recordLocalizationAccess && $languageAccess; } @@ -807,6 +799,9 @@ class BackendUserAuthentication extends AbstractUserAuthentication } } // Checking languages: + if ($table === 'pages' && $checkFullLanguageAccess && !$this->checkFullLanguagesAccess($table, $idOrRow)) { + return false; + } if ($GLOBALS['TCA'][$table]['ctrl']['languageField']) { // Language field must be found in input row - otherwise it does not make sense. if (isset($idOrRow[$GLOBALS['TCA'][$table]['ctrl']['languageField']])) { @@ -826,11 +821,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication . $GLOBALS['TCA'][$table]['ctrl']['languageField'] . '" was not found in testing record!'; return false; } - } elseif ( - $table === 'pages' && $checkFullLanguageAccess && - !$this->checkFullLanguagesAccess($table, $idOrRow) - ) { - return false; } // Checking authMode fields: if (is_array($GLOBALS['TCA'][$table]['columns'])) { diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php index 3d049826bf013a26fb18654dccc6167039c715a1..53c95637e4bf375ba98d2fd7cea8d8c16366923e 100644 --- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php +++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php @@ -1043,7 +1043,12 @@ class DataHandler implements LoggerAwareInterface // Now, check if we may insert records on this pid. if ($theRealPid >= 0) { // Checks if records can be inserted on this $pid. - $recordAccess = $this->checkRecordInsertAccess($table, $theRealPid); + // If this is a page translation, the check needs to be done for the l10n_parent record + if ($table === 'pages' && $incomingFieldArray['sys_language_uid'] > 0 && $incomingFieldArray['l10n_parent'] > 0) { + $recordAccess = $this->checkRecordInsertAccess($table, $incomingFieldArray['l10n_parent']); + } else { + $recordAccess = $this->checkRecordInsertAccess($table, $theRealPid); + } if ($recordAccess) { $this->addDefaultPermittedLanguageIfNotSet($table, $incomingFieldArray); $recordAccess = $this->BE_USER->recordEditAccessInternals($table, $incomingFieldArray, true); @@ -1417,19 +1422,26 @@ class DataHandler implements LoggerAwareInterface if (is_array($incomingFieldArray) && is_array($checkValueRecord)) { ArrayUtility::mergeRecursiveWithOverrule($checkValueRecord, $incomingFieldArray); } + $currentRecord = $checkValueRecord; } else { // We must use the current values as basis for this! $currentRecord = ($checkValueRecord = $this->recordInfo($table, $id, '*')); - // This is done to make the pid positive for offline versions; Necessary to have diff-view for pages_language_overlay in workspaces. + // This is done to make the pid positive for offline versions; Necessary to have diff-view for page translations in workspaces. BackendUtility::fixVersioningPid($table, $currentRecord); - // Get original language record if available: - if (is_array($currentRecord) && $GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField'] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0 && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] && (int)$currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] > 0) { - $lookUpTable = $table === 'pages_language_overlay' ? 'pages' : $table; - $originalLanguageRecord = $this->recordInfo($lookUpTable, $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']], '*'); - BackendUtility::workspaceOL($lookUpTable, $originalLanguageRecord); - $originalLanguage_diffStorage = unserialize($currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField']]); - } } + + // Get original language record if available: + if (is_array($currentRecord) + && $GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField'] + && $GLOBALS['TCA'][$table]['ctrl']['languageField'] + && $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0 + && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] + && (int)$currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] > 0) { + $originalLanguageRecord = $this->recordInfo($table, $currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']], '*'); + BackendUtility::workspaceOL($table, $originalLanguageRecord); + $originalLanguage_diffStorage = unserialize($currentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField']]); + } + $this->checkValue_currentRecord = $checkValueRecord; // In the following all incoming value-fields are tested: // - Are the user allowed to change the field? @@ -1464,8 +1476,6 @@ class DataHandler implements LoggerAwareInterface $value = (int)$fieldValue; switch ($field) { case 'perms_userid': - $fieldArray[$field] = $value; - break; case 'perms_groupid': $fieldArray[$field] = $value; break; @@ -1518,6 +1528,17 @@ class DataHandler implements LoggerAwareInterface } } } + + // Dealing with a page translation, setting "sorting", "pid", "perms_*" to the same values as the original record + if ($table === 'pages' && is_array($originalLanguageRecord)) { + $fieldArray['sorting'] = $originalLanguageRecord['sorting']; + $fieldArray['perms_userid'] = $originalLanguageRecord['perms_userid']; + $fieldArray['perms_groupid'] = $originalLanguageRecord['perms_groupid']; + $fieldArray['perms_user'] = $originalLanguageRecord['perms_user']; + $fieldArray['perms_group'] = $originalLanguageRecord['perms_group']; + $fieldArray['perms_everybody'] = $originalLanguageRecord['perms_everybody']; + } + // Add diff-storage information: if ($diffStorageFlag && !isset($fieldArray[$GLOBALS['TCA'][$table]['ctrl']['transOrigDiffSourceField']])) { // If the field is set it would probably be because of an undo-operation - in which case we should not update the field of course... @@ -1552,7 +1573,7 @@ class DataHandler implements LoggerAwareInterface $res = []; // Processing special case of field pages.doktype - if (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') { + if ($table === 'pages' && $field === 'doktype') { // If the user may not use this specific doktype, we issue a warning if (!($this->admin || GeneralUtility::inList($this->BE_USER->groupData['pagetypes_select'], $value))) { if ($this->enableLogging) { @@ -3381,7 +3402,7 @@ class DataHandler implements LoggerAwareInterface } $fullLanguageCheckNeeded = $table !== 'pages'; - //Used to check language and general editing rights + // Used to check language and general editing rights if (!$ignoreLocalization && ($language <= 0 || !$this->BE_USER->checkLanguageAccess($language)) && !$this->BE_USER->recordEditAccessInternals($table, $uid, false, false, $fullLanguageCheckNeeded)) { $this->log($table, $uid, 1, 0, 1, 'Attempt to copy record "%s:%s" without having permissions to do so. [' . $this->BE_USER->errorMsg . '].', -1, [$table, $uid]); return null; @@ -4174,8 +4195,8 @@ class DataHandler implements LoggerAwareInterface */ public function copyL10nOverlayRecords($table, $uid, $destPid, $first = false, $overrideValues = [], $excludeFields = '') { - // There's no need to perform this for page-records or for tables that are not localizable - if (!BackendUtility::isTableLocalizable($table) || $table === 'pages' || $table === 'pages_language_overlay') { + // There's no need to perform this for tables that are not localizable + if (!BackendUtility::isTableLocalizable($table)) { return; } @@ -4396,6 +4417,20 @@ class DataHandler implements LoggerAwareInterface if ($GLOBALS['TCA'][$table]['ctrl']['tstamp']) { $updateFields[$GLOBALS['TCA'][$table]['ctrl']['tstamp']] = $GLOBALS['EXEC_TIME']; } + + // Check if this is a translation of a page, if so then it just needs to be kept "sorting" in sync + // Usually called from moveL10nOverlayRecords() + $originalTranslationRecord = null; + if ($table === 'pages') { + $fullRecord = $this->recordInfo($table, $uid, 'sys_language_uid, l10n_parent'); + if ($fullRecord['sys_language_uid'] > 0) { + $originalTranslationRecord = $this->recordInfo($table, $fullRecord['l10n_parent'], 'pid,' . $sortRow); + $updateFields[$sortRow] = $originalTranslationRecord[$sortRow]; + // Ensure that the PID is always the same as the original page + $destPid = $originalTranslationRecord['pid']; + } + } + // Insert as first element on page (where uid = $destPid) if ($destPid >= 0) { if ($table !== 'pages' || $this->destNotInsideSelf($destPid, $uid)) { @@ -4405,7 +4440,7 @@ class DataHandler implements LoggerAwareInterface // Setting PID $updateFields['pid'] = $destPid; // Table is sorted by 'sortby' - if ($sortRow) { + if ($sortRow && !isset($updateFields[$sortRow])) { $sortNumber = $this->getSortNumber($table, $uid, $destPid); $updateFields[$sortRow] = $sortNumber; } @@ -4464,9 +4499,11 @@ class DataHandler implements LoggerAwareInterface if ($table !== 'pages' || $this->destNotInsideSelf($destPid, $uid)) { // clear cache before moving $this->registerRecordIdForPageCacheClearing($table, $uid); - // We now update the pid and sortnumber + // We now update the pid and sortnumber (if not set for page translations) $updateFields['pid'] = $destPid; - $updateFields[$sortRow] = $sortInfo['sortNumber']; + if (!isset($updateFields[$sortRow])) { + $updateFields[$sortRow] = $sortInfo['sortNumber']; + } // Check for child records that have also to be moved $this->moveRecord_procFields($table, $uid, $destPid); // Create query for update: @@ -4582,8 +4619,8 @@ class DataHandler implements LoggerAwareInterface */ public function moveL10nOverlayRecords($table, $uid, $destPid, $originalRecordDestinationPid) { - // There's no need to perform this for page-records or not localizable tables - if (!BackendUtility::isTableLocalizable($table) || $table === 'pages' || $table === 'pages_language_overlay') { + // There's no need to perform this for non-localizable tables + if (!BackendUtility::isTableLocalizable($table)) { return; } @@ -4652,10 +4689,7 @@ class DataHandler implements LoggerAwareInterface } $this->registerNestedElementCall($table, $uid, 'localize'); - if ((!$GLOBALS['TCA'][$table]['ctrl']['languageField'] - || !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] - || $table === 'pages_language_overlay') - && $table !== 'pages') { + if (!$GLOBALS['TCA'][$table]['ctrl']['languageField'] || !$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) { $this->newlog('Localization failed; "languageField" and "transOrigPointerField" must be defined for the table!', 1); return false; } @@ -4680,8 +4714,7 @@ class DataHandler implements LoggerAwareInterface // Make sure that records which are translated from another language than the default language have a correct // localization source set themselves, before translating them to another language. if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] !== 0 - && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0 - && $table !== 'pages') { + && $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) { $localizationParentRecord = BackendUtility::getRecord( $table, $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] @@ -4694,41 +4727,12 @@ class DataHandler implements LoggerAwareInterface // Default language records must never have a localization parent as they are the origin of any translation. if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] !== 0 - && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0 - && $table !== 'pages') { + && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0) { $this->newlog('Localization failed; Source record contained a reference to an original default record but is a default record itself (which is strange)!', 1); return false; } - if ($table === 'pages') { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); - $queryBuilder->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); - - $recordCount = $queryBuilder->count('*') - ->from('pages_language_overlay') - ->where( - $queryBuilder->expr()->eq( - 'pid', - $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT) - ), - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages_language_overlay']['ctrl']['languageField'], - $queryBuilder->createNamedParameter((int)$langRec['uid'], \PDO::PARAM_INT) - ) - ) - ->execute() - ->fetchColumn(0); - - $pass = !$recordCount; - $Ttable = 'pages_language_overlay'; - } else { - $pass = !BackendUtility::getRecordLocalization($table, $uid, $langRec['uid'], 'AND pid=' . (int)$row['pid']); - $Ttable = $table; - } + $pass = !BackendUtility::getRecordLocalization($table, $uid, $language, 'AND pid=' . (int)$row['pid']); if (!$pass) { $this->newlog('Localization failed; There already was a localization for this language of the record!', 1); @@ -4739,26 +4743,26 @@ class DataHandler implements LoggerAwareInterface $overrideValues = []; $excludeFields = []; // Set override values: - $overrideValues[$GLOBALS['TCA'][$Ttable]['ctrl']['languageField']] = $langRec['uid']; + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['languageField']] = $langRec['uid']; // If the translated record is a default language record, set it's uid as localization parent of the new record. // If translating from any other language, no override is needed; we just can copy the localization parent of // the original record (which is pointing to the correspondent default language record) to the new record. // In copy / free mode the TransOrigPointer field is always set to 0, as no connection to the localization parent is wanted in that case. - if (($this->useTransOrigPointerField && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0) - || $table === 'pages') { - $overrideValues[$GLOBALS['TCA'][$Ttable]['ctrl']['transOrigPointerField']] = $uid; + // For pages, there is no "copy/free mode". + if (($this->useTransOrigPointerField || $table === 'pages') && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] === 0) { + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = $uid; } elseif (!$this->useTransOrigPointerField) { - $overrideValues[$GLOBALS['TCA'][$Ttable]['ctrl']['transOrigPointerField']] = 0; + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = 0; } if (isset($GLOBALS['TCA'][$table]['ctrl']['translationSource'])) { - $overrideValues[$GLOBALS['TCA'][$Ttable]['ctrl']['translationSource']] = $uid; + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['translationSource']] = $uid; } // Copy the type (if defined in both tables) from the original record so that translation has same type as original record - if (isset($GLOBALS['TCA'][$table]['ctrl']['type']) && isset($GLOBALS['TCA'][$Ttable]['ctrl']['type'])) { - $overrideValues[$GLOBALS['TCA'][$Ttable]['ctrl']['type']] = $row[$GLOBALS['TCA'][$table]['ctrl']['type']]; + if (isset($GLOBALS['TCA'][$table]['ctrl']['type'])) { + $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['type']] = $row[$GLOBALS['TCA'][$table]['ctrl']['type']]; } // Set exclude Fields: - foreach ($GLOBALS['TCA'][$Ttable]['columns'] as $fN => $fCfg) { + foreach ($GLOBALS['TCA'][$table]['columns'] as $fN => $fCfg) { $translateToMsg = ''; // Check if we are just prefixing: if ($fCfg['l10n_mode'] === 'prefixLangTitle') { @@ -4785,15 +4789,16 @@ class DataHandler implements LoggerAwareInterface } } elseif ( ($fCfg['l10n_mode'] === 'exclude') - && $fN != $GLOBALS['TCA'][$Ttable]['ctrl']['languageField'] - && $fN != $GLOBALS['TCA'][$Ttable]['ctrl']['transOrigPointerField'] + && $fN != $GLOBALS['TCA'][$table]['ctrl']['languageField'] + && $fN != $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ) { // Otherwise, do not copy field (unless it is the language field or // pointer to the original language) $excludeFields[] = $fN; } } - if ($Ttable === $table) { + + if ($table !== 'pages') { // Get the uid of record after which this localized record should be inserted $previousUid = $this->getPreviousLocalizedRecordUid($table, $uid, $row['pid'], $language); // Execute the copy: @@ -4803,16 +4808,17 @@ class DataHandler implements LoggerAwareInterface $this->triggerRemapAction($table, $newId, [$this, 'placeholderShadowing'], [$table, $autoVersionNewId], true); } } else { - // Create new record: + // Create new page which needs to contain the same pid as the original page + $overrideValues['pid'] = $row['pid']; $temporaryId = StringUtility::getUniqueId('NEW'); $copyTCE = $this->getLocalTCE(); - $copyTCE->start([$Ttable => [$temporaryId => $overrideValues]], [], $this->BE_USER); + $copyTCE->start([$table => [$temporaryId => $overrideValues]], [], $this->BE_USER); $copyTCE->process_datamap(); // Getting the new UID as if it had been copied: $theNewSQLID = $copyTCE->substNEWwithIDs[$temporaryId]; if ($theNewSQLID) { - // If is by design that $Ttable is used and not $table! See "l10nmgr" extension. Could be debated, but this is what I chose for this "pseudo case" - $this->copyMappingArray[$Ttable][$uid] = $theNewSQLID; + // If is by design that $table is used and not $table! See "l10nmgr" extension. Could be debated, but this is what I chose for this "pseudo case" + $this->copyMappingArray[$table][$uid] = $theNewSQLID; $newId = $theNewSQLID; } } @@ -4883,7 +4889,6 @@ class DataHandler implements LoggerAwareInterface $foreignTable = $config['foreign_table']; $transOrigPointer = (int)$parentRecord[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; - $transOrigTable = BackendUtility::getOriginalTranslationTable($table); $childTransOrigPointerField = $GLOBALS['TCA'][$foreignTable]['ctrl']['transOrigPointerField']; if (!$parentRecord || !is_array($parentRecord) || $language <= 0 || !$transOrigPointer) { @@ -4895,14 +4900,14 @@ class DataHandler implements LoggerAwareInterface return; } - $transOrigRecord = BackendUtility::getRecordWSOL($transOrigTable, $transOrigPointer); + $transOrigRecord = BackendUtility::getRecordWSOL($table, $transOrigPointer); $removeArray = []; $mmTable = $inlineSubType === 'mm' && isset($config['MM']) && $config['MM'] ? $config['MM'] : ''; // Fetch children from original language parent: /** @var $dbAnalysisOriginal RelationHandler */ $dbAnalysisOriginal = $this->createRelationHandlerInstance(); - $dbAnalysisOriginal->start($transOrigRecord[$field], $foreignTable, $mmTable, $transOrigRecord['uid'], $transOrigTable, $config); + $dbAnalysisOriginal->start($transOrigRecord[$field], $foreignTable, $mmTable, $transOrigRecord['uid'], $table, $config); $elementsOriginal = []; foreach ($dbAnalysisOriginal->itemArray as $item) { $elementsOriginal[$item['id']] = $item; @@ -5090,7 +5095,15 @@ class DataHandler implements LoggerAwareInterface // Checking if there is anything else disallowing deleting the record by checking if editing is allowed $deletedRecord = $forceHardDelete || $undeleteRecord; - $hasEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, false, $deletedRecord, true); + $fullLanguageAccessCheck = true; + if ($table === 'pages') { + // If this is a page translation, the full language access check should not be done + $recordInfo = $this->recordInfo($table, $uid, 'l10n_parent'); + if ($recordInfo['l10n_parent'] > 0) { + $fullLanguageAccessCheck = false; + } + } + $hasEditAccess = $this->BE_USER->recordEditAccessInternals($table, $uid, false, $deletedRecord, $fullLanguageAccessCheck); if (!$hasEditAccess) { $this->log($table, $uid, 3, 0, 1, 'Attempt to delete record without delete-permissions'); return; @@ -5403,9 +5416,19 @@ class DataHandler implements LoggerAwareInterface public function canDeletePage($uid) { $uid = (int)$uid; + $isTranslatedPage = null; // If we may at all delete this page - if (!$this->doesRecordExist('pages', $uid, 'delete')) { + // If this is a page translation, do the check against the perms_* of the default page + // Because it is currently only deleting the translation + $fullRecord = $this->recordInfo('pages', $uid, 'l10n_parent'); + if ($fullRecord['l10n_parent'] > 0) { + if ($this->doesRecordExist('pages', (int)$fullRecord['l10n_parent'], 'delete')) { + $isTranslatedPage = $fullRecord['l10n_parent'] > 0; + } else { + return 'Attempt to delete page without permissions'; + } + } elseif (!$this->doesRecordExist('pages', $uid, 'delete')) { return 'Attempt to delete page without permissions'; } @@ -5433,7 +5456,7 @@ class DataHandler implements LoggerAwareInterface } foreach ($pagesInBranch as $pageInBranch) { - if (!$this->BE_USER->recordEditAccessInternals('pages', $pageInBranch, false, false, true)) { + if (!$this->BE_USER->recordEditAccessInternals('pages', $pageInBranch, false, false, $isTranslatedPage ? false : true)) { return 'Attempt to delete page which has prohibited localizations.'; } } @@ -5563,8 +5586,8 @@ class DataHandler implements LoggerAwareInterface */ public function deleteL10nOverlayRecords($table, $uid) { - // Check whether table can be localized or has a different table defined to store localizations: - if (!BackendUtility::isTableLocalizable($table) || $table === 'pages' || $table === 'pages_language_overlay') { + // Check whether table can be localized + if (!BackendUtility::isTableLocalizable($table)) { return; } @@ -6062,8 +6085,14 @@ class DataHandler implements LoggerAwareInterface $thePidToUpdate = $this->registerDBPids[$table][$uid]; $thePidToUpdate = $this->copyMappingArray_merged['pages'][$thePidToUpdate]; } + // Update child records if change to pid is required (only if the current record is not on a workspace): if ($thePidToUpdate) { + // Ensure that only the default language page is used as PID + $localizationParent = $this->recordInfo('pages', $thePidToUpdate, 'l10n_parent'); + if ($localizationParent['l10n_parent'] > 0) { + $thePidToUpdate = $localizationParent['l10n_parent']; + } // ensure, only live page ids are used as 'pid' values $liveId = BackendUtility::getLiveVersionIdOfRecord('pages', $theUidToUpdate); if ($liveId !== null) { @@ -6448,7 +6477,15 @@ class DataHandler implements LoggerAwareInterface if (isset($this->recUpdateAccessCache[$table][$id])) { return $this->recUpdateAccessCache[$table][$id]; } - if ($this->doesRecordExist($table, $id, 'edit')) { + // permissions check for page translations need to be done on the parent page + if ($table === 'pages') { + $defaultLanguagePage = $this->recordInfo($table, $id, 'l10n_parent'); + if ($defaultLanguagePage['l10n_parent'] > 0) { + $res = $this->doesRecordExist($table, $defaultLanguagePage['l10n_parent'], 'edit'); + } else { + $res = $this->doesRecordExist($table, $id, 'edit') ? 1 : 0; + } + } elseif ($this->doesRecordExist($table, $id, 'edit')) { $res = 1; } // Cache the result @@ -8368,9 +8405,11 @@ class DataHandler implements LoggerAwareInterface if (empty($TSConfig['clearCache_disable'])) { // If table is "pages": $pageIdsThatNeedCacheFlush = []; - if ($table === 'pages' || $table === 'pages_language_overlay') { - if ($table === 'pages_language_overlay') { - $pageUid = $this->getPID($table, $uid); + if ($table === 'pages') { + // Find out if the record is a get the original page + $row = $this->recordInfo($table, $uid, 'pid,sys_language_uid,l10n_parent'); + if ((int)$row['l10n_parent'] > 0) { + $pageUid = $row['l10n_parent']; } else { $pageUid = $uid; } diff --git a/typo3/sysext/core/Classes/DataHandling/Localization/DataMapItem.php b/typo3/sysext/core/Classes/DataHandling/Localization/DataMapItem.php index 4cf0e7ab838e9de664d6b03835797da4b1e68491..21fb7e7c998642754aa3485c982b0b7de186fd4c 100644 --- a/typo3/sysext/core/Classes/DataHandling/Localization/DataMapItem.php +++ b/typo3/sysext/core/Classes/DataHandling/Localization/DataMapItem.php @@ -161,32 +161,6 @@ class DataMapItem return $this->tableName; } - /** - * Gets the table name used to resolve the language parent record. - * - * @return string - */ - public function getFromTableName(): string - { - if ($this->tableName === 'pages_language_overlay') { - return 'pages'; - } - return $this->tableName; - } - - /** - * Gets the table name used to resolve any kind of translations. - * - * @return string - */ - public function getForTableName(): string - { - if ($this->tableName === 'pages') { - return 'pages_language_overlay'; - } - return $this->tableName; - } - /** * Gets the id of this data-map item. * diff --git a/typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php b/typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php index 4f5daa40f5c1fd7b9f5e1d7bd8d803c4d1a8d435..33784b29b745b247ccf962d125a809c4e3edd2cf 100644 --- a/typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php +++ b/typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php @@ -141,41 +141,32 @@ class DataMapProcessor */ protected function collectItems(string $tableName, array $idValues) { - $forTableName = $tableName; - if ($forTableName === 'pages') { - $forTableName = 'pages_language_overlay'; - } - - if (!$this->isApplicable($forTableName)) { + if (!$this->isApplicable($tableName)) { return; } $fieldNames = [ 'uid' => 'uid', 'l10n_state' => 'l10n_state', - 'language' => $GLOBALS['TCA'][$forTableName]['ctrl']['languageField'], - 'parent' => $GLOBALS['TCA'][$forTableName]['ctrl']['transOrigPointerField'], + 'language' => $GLOBALS['TCA'][$tableName]['ctrl']['languageField'], + 'parent' => $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'], ]; - if (!empty($GLOBALS['TCA'][$forTableName]['ctrl']['translationSource'])) { - $fieldNames['source'] = $GLOBALS['TCA'][$forTableName]['ctrl']['translationSource']; + if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['translationSource'])) { + $fieldNames['source'] = $GLOBALS['TCA'][$tableName]['ctrl']['translationSource']; } - $translationValues = []; - // Fetching parent/source pointer values does not make sense for pages - if ($tableName !== 'pages') { - $translationValues = $this->fetchTranslationValues( + $translationValues = $this->fetchTranslationValues( + $tableName, + $fieldNames, + $this->filterNewItemIds( $tableName, - $fieldNames, - $this->filterNewItemIds( - $tableName, - $this->filterNumericIds(array_keys($idValues)) - ) - ); - } + $this->filterNumericIds(array_keys($idValues)) + ) + ); $dependencies = $this->fetchDependencies( - $forTableName, - $this->filterNewItemIds($forTableName, array_keys($idValues)) + $tableName, + $this->filterNewItemIds($tableName, array_keys($idValues)) ); foreach ($idValues as $id => $values) { @@ -297,7 +288,7 @@ class DataMapProcessor $fromRecord = ['uid' => $fromId]; if (MathUtility::canBeInterpretedAsInteger($fromId)) { $fromRecord = BackendUtility::getRecordWSOL( - $item->getFromTableName(), + $item->getTableName(), $fromId, $fieldNameList ); @@ -390,8 +381,8 @@ class DataMapProcessor $fromId = $fromRecord['uid']; // retrieve value from in-memory data-map - if ($this->isSetInDataMap($item->getFromTableName(), $fromId, $fieldName)) { - $fromValue = $this->allDataMap[$item->getFromTableName()][$fromId][$fieldName]; + if ($this->isSetInDataMap($item->getTableName(), $fromId, $fieldName)) { + $fromValue = $this->allDataMap[$item->getTableName()][$fromId][$fieldName]; } elseif (array_key_exists($fieldName, $fromRecord)) { // retrieve value from record $fromValue = $fromRecord[$fieldName]; @@ -401,13 +392,13 @@ class DataMapProcessor } // plain values - if (!$this->isRelationField($item->getFromTableName(), $fieldName)) { + if (!$this->isRelationField($item->getTableName(), $fieldName)) { $this->modifyDataMap( $item->getTableName(), $item->getId(), [$fieldName => $fromValue] ); - } elseif (!$this->isInlineRelationField($item->getFromTableName(), $fieldName)) { + } elseif (!$this->isInlineRelationField($item->getTableName(), $fieldName)) { // direct relational values $this->synchronizeDirectRelations($item, $fieldName, $fromRecord); } else { @@ -425,12 +416,12 @@ class DataMapProcessor */ protected function synchronizeDirectRelations(DataMapItem $item, string $fieldName, array $fromRecord) { - $configuration = $GLOBALS['TCA'][$item->getFromTableName()]['columns'][$fieldName]; + $configuration = $GLOBALS['TCA'][$item->getTableName()]['columns'][$fieldName]; $isSpecialLanguageField = ($configuration['config']['special'] ?? null) === 'languages'; $fromId = $fromRecord['uid']; - if ($this->isSetInDataMap($item->getFromTableName(), $fromId, $fieldName)) { - $fromValue = $this->allDataMap[$item->getFromTableName()][$fromId][$fieldName]; + if ($this->isSetInDataMap($item->getTableName(), $fromId, $fieldName)) { + $fromValue = $this->allDataMap[$item->getTableName()][$fromId][$fieldName]; } else { $fromValue = $fromRecord[$fieldName]; } @@ -439,7 +430,7 @@ class DataMapProcessor // if values are available in data-map already, just use them as well if ( empty($configuration['config']['MM']) - || $this->isSetInDataMap($item->getFromTableName(), $fromId, $fieldName) + || $this->isSetInDataMap($item->getTableName(), $fromId, $fieldName) || $isSpecialLanguageField ) { $this->modifyDataMap( @@ -470,7 +461,7 @@ class DataMapProcessor $tableNames, $manyToManyTable, $fromId, - $item->getFromTableName(), + $item->getTableName(), $configuration['config'] ); @@ -494,7 +485,7 @@ class DataMapProcessor */ protected function synchronizeInlineRelations(DataMapItem $item, string $fieldName, array $fromRecord, array $forRecord) { - $configuration = $GLOBALS['TCA'][$item->getFromTableName()]['columns'][$fieldName]; + $configuration = $GLOBALS['TCA'][$item->getTableName()]['columns'][$fieldName]; $isLocalizationModeExclude = ($configuration['l10n_mode'] ?? null) === 'exclude'; $foreignTableName = $configuration['config']['foreign_table']; @@ -652,16 +643,16 @@ class DataMapProcessor { $suggestedAncestorIds = []; $fromId = $fromRecord['uid']; - $configuration = $GLOBALS['TCA'][$item->getFromTableName()]['columns'][$fieldName]; + $configuration = $GLOBALS['TCA'][$item->getTableName()]['columns'][$fieldName]; $foreignTableName = $configuration['config']['foreign_table']; $manyToManyTable = ($configuration['config']['MM'] ?? ''); // determine suggested elements of either translation parent or source record // from data-map, in case the accordant language parent/source record was modified - if ($this->isSetInDataMap($item->getFromTableName(), $fromId, $fieldName)) { + if ($this->isSetInDataMap($item->getTableName(), $fromId, $fieldName)) { $suggestedAncestorIds = GeneralUtility::trimExplode( ',', - $this->allDataMap[$item->getFromTableName()][$fromId][$fieldName], + $this->allDataMap[$item->getTableName()][$fromId][$fieldName], true ); } elseif (MathUtility::canBeInterpretedAsInteger($fromId)) { @@ -672,7 +663,7 @@ class DataMapProcessor $foreignTableName, $manyToManyTable, $fromId, - $item->getFromTableName(), + $item->getTableName(), $configuration['config'] ); $suggestedAncestorIds = $this->mapRelationItemId($relationHandler->itemArray); @@ -692,7 +683,7 @@ class DataMapProcessor private function resolvePersistedInlineRelations(DataMapItem $item, string $fieldName, array $forRecord): array { $persistedIds = []; - $configuration = $GLOBALS['TCA'][$item->getFromTableName()]['columns'][$fieldName]; + $configuration = $GLOBALS['TCA'][$item->getTableName()]['columns'][$fieldName]; $foreignTableName = $configuration['config']['foreign_table']; $manyToManyTable = ($configuration['config']['MM'] ?? ''); @@ -789,8 +780,7 @@ class DataMapProcessor /** * Fetches translation related field values for the items submitted in - * the data-map. That's why further adjustment for the tables pages vs. - * pages_language_overlay is not required. + * the data-map. * * @param string $tableName * @param array $fieldNames @@ -842,10 +832,6 @@ class DataMapProcessor */ protected function fetchDependencies(string $tableName, array $ids) { - if ($tableName === 'pages') { - $tableName = 'pages_language_overlay'; - } - if (!BackendUtility::isTableLocalizable($tableName)) { return []; } @@ -923,10 +909,6 @@ class DataMapProcessor */ protected function fetchDependentIdMap(string $tableName, array $ids, int $desiredLanguage) { - if ($tableName === 'pages') { - $tableName = 'pages_language_overlay'; - } - $ids = $this->filterNumericIds($ids, true); $isTranslatable = BackendUtility::isTableLocalizable($tableName); $originFieldName = ($GLOBALS['TCA'][$tableName]['ctrl']['origUid'] ?? null); @@ -1341,10 +1323,6 @@ class DataMapProcessor */ protected function getPrefixLanguageTitleFieldNames(string $tableName) { - if ($tableName === 'pages') { - $tableName = 'pages_language_overlay'; - } - $prefixLanguageTitleFieldNames = []; if (empty($GLOBALS['TCA'][$tableName]['columns'])) { return $prefixLanguageTitleFieldNames; diff --git a/typo3/sysext/core/Classes/Migrations/TcaMigration.php b/typo3/sysext/core/Classes/Migrations/TcaMigration.php index f54f61bcbdab87316bed66f20bf1714730de23fa..2add591b020053cfa638950f69f5dbcd75ccd48f 100644 --- a/typo3/sysext/core/Classes/Migrations/TcaMigration.php +++ b/typo3/sysext/core/Classes/Migrations/TcaMigration.php @@ -88,6 +88,7 @@ class TcaMigration $tca = $this->migrateinputDateTimeMax($tca); $tca = $this->migrateInlineOverrideChildTca($tca); $tca = $this->migrateLocalizeChildrenAtParentLocalization($tca); + $tca = $this->migratePagesLanguageOverlayRemoval($tca); return $tca; } @@ -975,70 +976,36 @@ class TcaMigration protected function migratePageLocalizationDefinitions(array $tca) { if ( - empty($tca['pages']['columns']) - || empty($tca['pages_language_overlay']['columns']) + empty($tca['pages_language_overlay']['columns']) ) { return $tca; } // ensure, that localization settings are defined for - // pages_language_overlay and not only for pages - foreach ($tca['pages']['columns'] as $fieldName => &$fieldConfig) { + // pages and not for pages_language_overlay + foreach ($tca['pages_language_overlay']['columns'] as $fieldName => &$fieldConfig) { $l10nMode = $fieldConfig['l10n_mode'] ?? null; $allowLanguageSynchronization = $fieldConfig['config']['behaviour']['allowLanguageSynchronization'] ?? null; - $oppositeFieldConfig = $tca['pages_language_overlay']['columns'][$fieldName] ?? []; + $oppositeFieldConfig = $tca['pages']['columns'][$fieldName] ?? []; $oppositeL10nMode = $oppositeFieldConfig['l10n_mode'] ?? null; $oppositeAllowLanguageSynchronization = $oppositeFieldConfig['config']['behaviour']['allowLanguageSynchronization'] ?? null; if ($l10nMode !== null) { if (!empty($oppositeFieldConfig) && $oppositeL10nMode !== 'exclude') { - $tca['pages_language_overlay']['columns'][$fieldName]['l10n_mode'] = $l10nMode; + $tca['pages']['columns'][$fieldName]['l10n_mode'] = $l10nMode; $this->messages[] = 'The TCA setting \'l10n_mode\' was migrated ' - . 'to TCA pages_language_overlay[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\'] ' - . 'from TCA pages[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']'; - } - unset($fieldConfig['l10n_mode']); - $this->messages[] = 'The TCA setting \'l10n_mode\' was removed ' - . 'in TCA pages[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']'; - } - - if (!empty($allowLanguageSynchronization)) { - if (!empty($oppositeFieldConfig) && empty($oppositeAllowLanguageSynchronization)) { - $tca['pages_language_overlay']['columns'][$fieldName]['config']['behaviour']['allowLanguageSynchronization'] = (bool)$allowLanguageSynchronization; - $this->messages[] = 'The TCA setting \'allowLanguageSynchronization\' was migrated ' - . 'to TCA pages_language_overlay[\'columns\'][\'' . $fieldName . '\']' - . '[\'config\'][\'behaviour\'][\'allowLanguageSynchronization\'] ' - . 'from TCA pages[\'columns\'][\'' . $fieldName . '\']' - . '[\'config\'][\'behaviour\'][\'allowLanguageSynchronization\']'; + . 'to TCA pages[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\'] ' + . 'from TCA pages_language_overlay[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']'; } - unset($fieldConfig['config']['behaviour']['allowLanguageSynchronization']); - $this->messages[] = 'The TCA setting \'allowLanguageSynchronization\' was removed ' - . 'in TCA pages[\'columns\'][\'' . $fieldName . '\']' - . '[\'config\'][\'behaviour\'][\'allowLanguageSynchronization\']'; - } - } - - // clean up localization settings in pages_language_overlay that cannot - // be used since the fields in pages are just not configured/available - foreach ($tca['pages_language_overlay']['columns'] as $fieldName => &$fieldConfig) { - $l10nMode = $fieldConfig['l10n_mode'] ?? null; - $allowLanguageSynchronization = $fieldConfig['config']['behaviour']['allowLanguageSynchronization'] ?? null; - $oppositeFieldConfig = $tca['pages']['columns'][$fieldName] ?? []; - - if (!empty($oppositeFieldConfig)) { - continue; } - if ($l10nMode !== null) { - unset($fieldConfig['l10n_mode']); - $this->messages[] = 'The TCA setting \'l10n_mode\' was removed ' - . 'in TCA pages_language_overlay[\'columns\'][\'' . $fieldName . '\'][\'l10n_mode\']'; - } - if (!empty($allowLanguageSynchronization)) { - unset($fieldConfig['config']['behaviour']['allowLanguageSynchronization']); - $this->messages[] = 'The TCA setting \'allowLanguageSynchronization\' was removed ' - . 'in TCA pages[\'columns\'][\'' . $fieldName . '\']' + if (!empty($allowLanguageSynchronization) && empty($oppositeAllowLanguageSynchronization)) { + $tca['pages']['columns'][$fieldName]['config']['behaviour']['allowLanguageSynchronization'] = (bool)$allowLanguageSynchronization; + $this->messages[] = 'The TCA setting \'allowLanguageSynchronization\' was migrated ' + . 'to TCA pages[\'columns\'][\'' . $fieldName . '\']' + . '[\'config\'][\'behaviour\'][\'allowLanguageSynchronization\'] ' + . 'from TCA pages_language_overlay[\'columns\'][\'' . $fieldName . '\']' . '[\'config\'][\'behaviour\'][\'allowLanguageSynchronization\']'; } } @@ -2561,4 +2528,21 @@ class TcaMigration } return $tca; } + + /** + * Removes $TCA['pages_language_overlay'] if defined. + * + * @param array $tca + * @return array the modified TCA structure + */ + protected function migratePagesLanguageOverlayRemoval(array $tca) + { + if (isset($tca['pages_language_overlay'])) { + $this->messages[] = 'The TCA table \'pages_language_overlay\' is' + . ' not used anymore and has been removed automatically in' + . ' order to avoid negative side-effects.'; + unset($tca['pages_language_overlay']); + } + return $tca; + } } diff --git a/typo3/sysext/core/Classes/Utility/RootlineUtility.php b/typo3/sysext/core/Classes/Utility/RootlineUtility.php index 5dba704bc54d4c91605cb11526e8bcf495505c85..a2e1908d8d10e8b743c4361953f9007152d837ec 100644 --- a/typo3/sysext/core/Classes/Utility/RootlineUtility.php +++ b/typo3/sysext/core/Classes/Utility/RootlineUtility.php @@ -273,7 +273,7 @@ class RootlineUtility /** * Resolve relations as defined in TCA and add them to the provided $pageRecord array. * - * @param int $uid Either pages.uid or pages_language_overlay.uid if localized + * @param int $uid page ID * @param array $pageRecord Page record (possibly overlaid) to be extended with relations * @throws \RuntimeException * @return array $pageRecord with additional relations @@ -336,7 +336,7 @@ class RootlineUtility $queryBuilder->expr()->eq( trim($configuration['foreign_table_field']), $queryBuilder->createNamedParameter( - (int)$this->languageUid > 0 ? 'pages_language_overlay' : 'pages', + 'pages', \PDO::PARAM_STR ) ) diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index 76001ce283ee86d8db6392def39edc5eabc6b8cc..99aeadf32b1f2c62c66406528f109a06949e71c4 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -322,8 +322,14 @@ return [ \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseEditRow::class, ], ], + \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseDefaultLanguagePageRow::class => [ + 'depends' => [ + \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseParentPageRow::class, + ], + ], \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseUserPermissionCheck::class => [ 'depends' => [ + \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseDefaultLanguagePageRow::class, \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseParentPageRow::class, \TYPO3\CMS\Backend\Form\FormDataProvider\InitializeProcessedTca::class, ], @@ -896,7 +902,6 @@ return [ sys_filemounts.after = be_users sys_file_storage.after = sys_filemounts sys_language.after = sys_file_storage - pages_language_overlay.before = pages fe_users.after = fe_groups fe_users.before = pages sys_template.after = pages diff --git a/typo3/sysext/core/Configuration/TCA/pages.php b/typo3/sysext/core/Configuration/TCA/pages.php index 99fc3a64ad0193d25e06c08fda2c6533be4b4a29..900f92e4e8e925828bdd32cce73cbd278e1b187d 100644 --- a/typo3/sysext/core/Configuration/TCA/pages.php +++ b/typo3/sysext/core/Configuration/TCA/pages.php @@ -15,6 +15,10 @@ return [ 'cruser_id' => 'cruser_id', 'editlock' => 'editlock', 'useColumnsForDefaultValues' => 'doktype,fe_group,hidden', + 'languageField' => 'sys_language_uid', + 'transOrigPointerField' => 'l10n_parent', + 'transOrigDiffSourceField' => 'l10n_diffsource', + 'translationSource' => 'l10n_source', 'enablecolumns' => [ 'disabled' => 'hidden', 'starttime' => 'starttime', @@ -128,6 +132,7 @@ return [ ] ], 'title' => [ + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:title', 'config' => [ 'type' => 'input', @@ -138,6 +143,7 @@ return [ ], 'TSconfig' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'TSconfig:', 'config' => [ 'type' => 'text', @@ -149,6 +155,7 @@ return [ ], 'php_tree_stop' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:php_tree_stop', 'config' => [ 'type' => 'check', @@ -169,6 +176,7 @@ return [ ], 'editlock' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:editlock', 'config' => [ 'type' => 'check', @@ -181,6 +189,7 @@ return [ ], 'hidden' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.hidden', 'config' => [ 'type' => 'check', @@ -194,6 +203,7 @@ return [ ], 'starttime' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.starttime', 'config' => [ 'type' => 'input', @@ -204,6 +214,7 @@ return [ ], 'endtime' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.endtime', 'config' => [ 'type' => 'input', @@ -215,8 +226,55 @@ return [ ] ] ], + 'l10n_parent' => [ + 'exclude' => true, + 'displayCond' => 'FIELD:sys_language_uid:>:0', + 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.l18n_parent', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + [ + '', + 0 + ] + ], + 'foreign_table' => 'pages', + // no sys_language_uid = -1 allowed explicitly! + 'foreign_table_where' => 'AND pages.uid=###CURRENT_PID### AND pages.sys_language_uid = 0', + 'default' => 0 + ] + ], + 'sys_language_uid' => [ + 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.language', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'sys_language', + 'foreign_table_where' => 'ORDER BY sys_language.sorting', + 'items' => [], // no default language here, as the pages table is always the default language + 'default' => 0, + 'fieldWizard' => [ + 'selectIcons' => [ + 'disabled' => false, + ], + ], + ] + ], + 'l10n_diffsource' => [ + 'config' => [ + 'type' => 'passthrough', + 'default' => '' + ] + ], + 'l10n_source' => [ + 'config' => [ + 'type' => 'passthrough' + ] + ], 'layout' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.layout', 'config' => [ 'type' => 'select', @@ -244,6 +302,7 @@ return [ ], 'fe_group' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.fe_group', 'config' => [ 'type' => 'select', @@ -272,6 +331,7 @@ return [ ], 'extendToSubpages' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.extendToSubpages', 'config' => [ 'type' => 'check', @@ -294,6 +354,7 @@ return [ ], 'nav_hide' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.nav_hide', 'config' => [ 'type' => 'check', @@ -306,6 +367,7 @@ return [ ], 'subtitle' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.subtitle', 'config' => [ 'type' => 'input', @@ -316,6 +378,7 @@ return [ ], 'target' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.target', 'config' => [ 'type' => 'input', @@ -332,6 +395,7 @@ return [ 'alias' => [ 'exclude' => true, 'displayCond' => 'VERSION:IS:false', + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.alias', 'config' => [ 'type' => 'input', @@ -348,7 +412,10 @@ return [ 'size' => 23, 'max' => 255, 'eval' => 'trim,required', - 'softref' => 'url' + 'softref' => 'url', + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'lastUpdated' => [ @@ -358,7 +425,10 @@ return [ 'type' => 'input', 'renderType' => 'inputDateTime', 'eval' => 'datetime', - 'default' => 0 + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'newUntil' => [ @@ -368,11 +438,15 @@ return [ 'type' => 'input', 'renderType' => 'inputDateTime', 'eval' => 'date', - 'default' => 0 + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'cache_timeout' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.cache_timeout', 'config' => [ 'type' => 'select', @@ -428,6 +502,7 @@ return [ ], 'cache_tags' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.cache_tags', 'config' => [ 'type' => 'input', @@ -445,6 +520,9 @@ return [ '1' => [ '0' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.no_search_checkbox_1_formlabel' ] + ], + 'behaviour' => [ + 'allowLanguageSynchronization' => true ] ] ], @@ -462,7 +540,10 @@ return [ 'additionalSearchFields' => 'nav_title, alias, url' ] ], - 'default' => 0 + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'shortcut_mode' => [ @@ -489,11 +570,15 @@ return [ \TYPO3\CMS\Frontend\Page\PageRepository::SHORTCUT_MODE_PARENT_PAGE ] ], - 'default' => 0 + 'default' => 0, + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'content_from_pid' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.content_from_pid', 'config' => [ 'type' => 'group', @@ -506,6 +591,7 @@ return [ ] ], 'mount_pid' => [ + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.mount_pid', 'config' => [ 'type' => 'group', @@ -519,6 +605,7 @@ return [ ], 'keywords' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.keywords', 'config' => [ 'type' => 'text', @@ -528,6 +615,7 @@ return [ ], 'description' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.description', 'config' => [ 'type' => 'text', @@ -537,6 +625,7 @@ return [ ], 'abstract' => [ 'exclude' => true, + 'l10n_mode' => 'prefixLangTitle', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.abstract', 'config' => [ 'type' => 'text', @@ -551,7 +640,10 @@ return [ 'type' => 'input', 'size' => 23, 'eval' => 'trim', - 'max' => 80 + 'max' => 80, + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'author_email' => [ @@ -562,7 +654,10 @@ return [ 'size' => 23, 'eval' => 'trim', 'max' => 80, - 'softref' => 'email[subst]' + 'softref' => 'email[subst]', + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ], 'media' => [ @@ -606,11 +701,15 @@ return [ ] ], ], + 'behaviour' => [ + 'allowLanguageSynchronization' => true + ] ] ) ], 'is_siteroot' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.is_siteroot', 'config' => [ 'type' => 'check', @@ -623,6 +722,7 @@ return [ ], 'mount_pid_ol' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.mount_pid_ol', 'config' => [ 'type' => 'radio', @@ -640,6 +740,7 @@ return [ ], 'module' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.module', 'config' => [ 'type' => 'select', @@ -661,6 +762,7 @@ return [ ], 'fe_login_mode' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.fe_login_mode', 'config' => [ 'type' => 'select', @@ -687,6 +789,7 @@ return [ ], 'l18n_cfg' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.l18n_cfg', 'config' => [ 'type' => 'check', @@ -704,6 +807,7 @@ return [ ], 'backend_layout' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.backend_layout_formlabel', 'config' => [ 'type' => 'select', @@ -719,11 +823,12 @@ return [ ], ], 'size' => 1, - 'maxitems' => 1, + 'maxitems' => 1 ] ], 'backend_layout_next_level' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.backend_layout_next_level_formlabel', 'config' => [ 'type' => 'select', @@ -739,11 +844,12 @@ return [ ], ], 'size' => 1, - 'maxitems' => 1, + 'maxitems' => 1 ] ], 'tsconfig_includes' => [ 'exclude' => true, + 'l10n_mode' => 'exclude', 'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.tsconfig_includes', 'config' => [ 'type' => 'select', diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-82445-PagesAndPageTranslations.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82445-PagesAndPageTranslations.rst new file mode 100644 index 0000000000000000000000000000000000000000..7eb88300a6a972de9d4af7940a57b56aa2c4daf4 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82445-PagesAndPageTranslations.rst @@ -0,0 +1,61 @@ +.. include:: ../../Includes.txt + +============================================== +Breaking: #82445 - Pages and page translations +============================================== + +See :issue:`82445` + +Description +=========== + +The database table "pages_language_overlay" has been obsoleted in the core and is +not used and updated anymore. Page translation records are now handled in the "pages" +table directly. + + +Impact +====== + +This change has a huge impact on page and page translation handling, especially +on database record level: + +* Table "pages_language_overlay" is no longer read by core code +* Records in "pages_language_overlay" are no longer updated by core code +* Records in "pages_language_overlay" are no longer shown in the backend +* Table and TCA definition for "pages_language_overlay" will be dropped in v10 +* Queries to table "pages" should now observe the "sys_language_uid" field to + fetch default language records only. A casual case for this are tree traversal + queries for children or rootline fetching. If additional restrictions are not + added, the query result may return page translations along the default language row. +* Existing inline relations with "foreign_table" and "foreign_field" and "foreign_table_field" + on a "pages_language_overlay" TCA are migrated to "pages". This works well for + typical FAL relations like the default "media" field. +* Complex TCA relations with "inline" "group" that use an "MM" table in TCA + not automatically get their relation record rows migrated. Configurations + like these are seldom and need manual migration steps depending on their + TCA configuration when upgrading. + + +Affected installations +====================== + +Single language instances are not affected. For sites with translations and +non-empty "pages_language_overlay" table, the main data merging is done with +upgrade wizards, but it may happen that TypoScript and extensions may need +adaptions, for instance if they write and read data from "pages" or +"pages_language_overlay" directly. + + +Migration +========= + +The following backwards-compatibility are met until TYPO3 v10.0: + +* The TCA definition for "pages_language_overlay" is kept as part of handling extensions supporting v8 and v9 +* The database table "pages_language_overlay" is kept as is, but not updated anymore by core +* A database field within "pages" is keeping the old pages_language_overlay record UID +* An upgrade wizard merges records from "pages_language_overlay" into "pages" +* An upgrade wizard adapts "be_groups" access restrictions for "pages_language_overlay" towards "pages" + +.. index:: Backend, Database, PHP-API, TCA, NotScanned diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82445-PageTranslationRelatedFunctionality.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82445-PageTranslationRelatedFunctionality.rst new file mode 100644 index 0000000000000000000000000000000000000000..bcfbb64dc895fa00ef9746bb93821afcbdb1de9f --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-82445-PageTranslationRelatedFunctionality.rst @@ -0,0 +1,47 @@ +.. include:: ../../Includes.txt + +============================================================ +Deprecation: #82445 - Page translation related functionality +============================================================ + +See :issue:`82445` + +Description +=========== + +With the merge of row content from table "pages_language_overlay" into "pages" +various core functionality has been deprecated. + +Methods: +* :php:`TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->getTranslationTable()` +* :php:`TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->isTranslationInOwnTable()` +* :php:`TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->foreignTranslationTable()` +* :php:`TYPO3\CMS\Backend\Utility\BackendUtility::getOriginalTranslationTable()` + +Additionally, the automatic TCA migration performed by the TYPO3 bootstrap now merges flags of type +:php:`['columns']['someField']['config']['behaviour']['allowLanguageSynchronization'] from +table "pages_language_overlay" into "pages". + + +Impact +====== + +A deprecation warning is thrown calling one of the above methods and if the TCA migration +changes the 'allowLanguageSynchronization' flag. + + +Affected Installations +====================== + +Instances using the above methods or TCA configuration. The install tool extension scanner will +find affected extensions and the TCA migrations check of the install tool shows applied TCA migrations. + + +Migration +========= + +The functionality to have language overlays records in a different table than the table the default language +records are in has been removed. It is safe to no longer check for this and use 'pages' for page language +overlay records directly. + +.. index:: Backend, PHP-API, TCA, FullyScanned diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-82445-MigratePagesLanguageOverlayIntoPages.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-82445-MigratePagesLanguageOverlayIntoPages.rst new file mode 100644 index 0000000000000000000000000000000000000000..20eb5928ca7388d6105539c2389940f0524448b0 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Important-82445-MigratePagesLanguageOverlayIntoPages.rst @@ -0,0 +1,53 @@ +.. include:: ../../Includes.txt + +============================================================= +Important: #82445 - Migrate pages_language_overlay into pages +============================================================= + +See :issue:`82445` + +Description +=========== + +The functionality of "pages_language_overlay" has been migrated into "pages". + +An upgrade wizard is in place to migrate all existing data into the "pages" database table. + +All relations directly to "pages_language_overlay" are migrated to the newly created "pages" records +as well. + +Some rules for future development need to be clarified: + +Definitions: + +**Default Language Page** + +- previously exclusively available in "pages" +- Holds the PID of the parent page +- MUST be in place in order to create a translated page (not possible to create a translated page without having a default page in place) +- Has always "l10n_parent" and "sys_language_uid" fields set to "0" +- The "uid" of this record is automatically the PID for all records of this page + +**Translated Page** (previously known as "pages_language_overlay") + +- Is identified as *Translated Page* by having a "sys_language_uid" field greater 0 and "l10n_parent" field containing the "uid" of the *Default Language Page*. +- The value of the "pid" field is the same "pid" as of the *Default Language Page* - effectively putting the *Translated Page* and the *Default Language Page* on the same root-level. +- The value of "sorting" is the same for all translated pages +- The "uid" field is not used by anything currently within the TYPO3 Core. +- The "hidden" field is set as "allowLanguageSynchronization" + + +**The following details apply** + +- Any TCA-based records (= subpages, content elements) still ALWAYS contain the pid to the *Original Language Page*, a DataHandler restriction ensures this constraint. +- Backend: All UI elements like Element Browser, Page Browser etc. are restricted to only show the *Default Translation Pages* to be selected (one can not link to a specific Translated Page). +- Permissions are always fetched from the "Original Language Page" +- DataHandler: Moving or deleting of a *Default Language Page* always moves/deletes the associated *Translated Page* records as well. +- DataHandler: "sorting" and "pid" parameters of translations are always kept in sync one-to-one for translated pages. Translated pages cannot be moved themselves. +- Permissions: Restricting a Backend User/Group to a language limits the access to "pages" to a specific language in page module. +- Permissions: All existing "pages_language_overlay" permissions are merged into "pages" options for all records - when a Backend User/Group is limited to only certain languages (and not the default language) this , the . If a Backend User/Group does have permission on "pages_language_overlay" but not "pages", the Backend User/Group has automatically assigned all translations (sys_language_uid) as language limitations. +- Frontend: Requesting a page can be done with ?id=originalpage&L=1 or ?id=translatedpage where "?id=translatedpage" internally resolves the "id" parameter to the uid of the Original Language Page and the "L" parameter resolved to the "sys_language_uid" corresponding in the TypoScript options. +- Frontend: All "pid" checks are always done against the Original Language Page, as all records still sit on that page. +- Frontend: Generating a link to a *Default Translation Page* with a current Translated Page generated, will exchange the target on link creation to the targeted Translated Page automatically. + +.. index:: Database, PHP-API diff --git a/typo3/sysext/core/Resources/Private/Language/locallang_csh_pageslol.xlf b/typo3/sysext/core/Resources/Private/Language/locallang_csh_pageslol.xlf deleted file mode 100644 index 1129ccdf585da5e51a0f0cc339c58de001d197ff..0000000000000000000000000000000000000000 --- a/typo3/sysext/core/Resources/Private/Language/locallang_csh_pageslol.xlf +++ /dev/null @@ -1,119 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> - <file t3:id="1415814798" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:32Z" product-name="context_help"> - <header/> - <body> - <trans-unit id=".description"> - <source>Represents an alternative language for the page.</source> - </trans-unit> - <trans-unit id=".details" xml:space="preserve"> - <source>These records contains fields very similar to the Page records, exactly those fields which should be translated to another language in case you want a localized version of the page. -Create only ONE Alternative Page Language record of a specific language in each page. Having more than one record will leave it uncertain which of them is used when the page is displayed. - -Before you can create Alternative Page Language records you should create a 'master' language to be available in the root of the website ("Website Language") -The TypoScript template must be configured to allow other languages as well. - -Technically when an alternative language is being viewed, the content of the Alternative Page Language record is simply overlaid on the actual page records thus substituting the content of the fields in the default language.</source> - </trans-unit> - <trans-unit id="_.seeAlso" xml:space="preserve"> - <source>sys_language, -_MOD_web_layout:language_list</source> - </trans-unit> - <trans-unit id="hidden.description"> - <source>Use this to temporarily disable the alternative language overlay for this page.</source> - </trans-unit> - <trans-unit id="hidden.details"> - <source>Setting this option is practical in the phase of adding the extra language. When it is set, the alternative content will not be displayed unless you - as an logged in backend user - enables the Admin Panel>Preview>Show hidden records option.</source> - </trans-unit> - <trans-unit id="_hidden.seeAlso" xml:space="preserve"> - <source>pages_language_overlay:starttime, -pages_language_overlay:endtime</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="starttime.description"> - <source>The 'Start' time determines the date from which the alternative language will be available online.</source> - </trans-unit> - <trans-unit id="_starttime.seeAlso" xml:space="preserve"> - <source>pages_language_overlay:endtime, -pages_language_overlay:hidden, -pages:starttime</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="endtime.description"> - <source>The 'End' time determines the date from which the alternative language will be available online.</source> - </trans-unit> - <trans-unit id="_endtime.seeAlso" xml:space="preserve"> - <source>pages_language_overlay:starttime, -pages_language_overlay:hidden, -pages:endtime</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="title.description"> - <source>Enter the title of the alternative language.</source> - </trans-unit> - <trans-unit id="_title.seeAlso"> - <source>pages:title</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="subtitle.description"> - <source>Enter the subtitle of the alternative language.</source> - </trans-unit> - <trans-unit id="_subtitle.seeAlso"> - <source>pages:subtitle</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="keywords.description"> - <source>Enter the keywords of the alternative language.</source> - </trans-unit> - <trans-unit id="_keywords.seeAlso"> - <source>pages:keywords</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="description.description"> - <source>Enter the description of the alternative language.</source> - </trans-unit> - <trans-unit id="_description.seeAlso"> - <source>pages:description</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="abstract.description"> - <source>Enter the abstract of the alternative language.</source> - </trans-unit> - <trans-unit id="_abstract.seeAlso"> - <source>pages:abstract</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="author.description"> - <source>Enter the author of the alternative language.</source> - </trans-unit> - <trans-unit id="_author.seeAlso"> - <source>pages:author</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="author_email.description"> - <source>Enter the author email address of the alternative language.</source> - </trans-unit> - <trans-unit id="_author_email.seeAlso"> - <source>pages:author_email</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="media.description"> - <source>Enter the media files of the alternative language.</source> - </trans-unit> - <trans-unit id="_media.seeAlso"> - <source>pages:media</source> - <note from="developer">This string contains an internal text, which must not be changed. Just copy the original text into the translation field. For more information have a look at the Tutorial.</note> - </trans-unit> - <trans-unit id="sys_language_uid.description"> - <source>Select the Alternative Language represented by this record.</source> - </trans-unit> - <trans-unit id="_sys_language_uid.seeAlso" xml:space="preserve"> - <source>sys_language, -sys_language:title</source> - </trans-unit> - <trans-unit id="nav_title.description"> - <source>Enter optional navigation title of the alternative language.</source> - </trans-unit> - </body> - </file> -</xliff> diff --git a/typo3/sysext/core/Resources/Private/Language/locallang_csh_syslang.xlf b/typo3/sysext/core/Resources/Private/Language/locallang_csh_syslang.xlf index bf69873230c034462ca02413c2a42032518532d0..460830ea1ad46694d2671fd308415b00adfa83b6 100644 --- a/typo3/sysext/core/Resources/Private/Language/locallang_csh_syslang.xlf +++ b/typo3/sysext/core/Resources/Private/Language/locallang_csh_syslang.xlf @@ -13,11 +13,7 @@ <source>Defines which languages are alternatively available on each webpage.</source> </trans-unit> <trans-unit id=".details" xml:space="preserve"> - <source>The Web>Page module has a feature which allows users to edit page content divided into not only columns but also languages. The languages available for translation are determined by the number of Website Language record created. -For a webpage to be available in another language an "Alternative Page Language" record must be created on the page.</source> - </trans-unit> - <trans-unit id="_.seeAlso"> - <source>pages_language_overlay</source> + <source>The Web>Page module has a feature which allows users to edit page content divided into not only columns but also languages. The languages available for translation are determined by the number of Website Language record created.</source> </trans-unit> </body> </file> diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php index fae8dcfdcb9ab6c78895e7d03da5e6e2fc6927c7..caf26096f77d6093ad45047dacd2a8192a7d3769 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php @@ -33,7 +33,6 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D const VALUE_LanguageIdSecond = 2; const TABLE_Page = 'pages'; - const TABLE_PageOverlay = 'pages_language_overlay'; const TABLE_Content = 'tt_content'; const TABLE_Hotel = 'tx_irretutorial_1nff_hotel'; const TABLE_Offer = 'tx_irretutorial_1nff_offer'; @@ -413,19 +412,21 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D public function localizePageWithLocalizationExclude() { $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude'; - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude'; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; } public function localizePageAndAddHotelChildWithLocalizationExclude() { $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude'; - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude'; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; $this->actionService->modifyRecords( self::VALUE_PageId, [ @@ -437,18 +438,22 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D public function localizePageWithLanguageSynchronization() { - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; + $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; } public function localizePageAndAddHotelChildWithLanguageSynchronization() { - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; + $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; $this->actionService->modifyRecords( self::VALUE_PageId, [ @@ -460,12 +465,14 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D public function localizePageAndAddMonoglotHotelChildWithLanguageSynchronization() { + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; unset($GLOBALS['TCA'][self::TABLE_Hotel]['ctrl']['languageField']); unset($GLOBALS['TCA'][self::TABLE_Hotel]['ctrl']['transOrigPointerField']); - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; + $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; $this->actionService->modifyRecords( self::VALUE_PageId, [ @@ -477,10 +484,12 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D public function localizeAndCopyPageWithLanguageSynchronization() { - $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; + $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; $newTableIds = $this->actionService->copyRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_PageIdTarget); $this->recordIds['newPageId'] = $newTableIds[self::TABLE_Page][self::VALUE_PageId]; } diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv index f14a18824ad08b129569ef2e3755613c090fbb1a..569284d74991ceefed1dcb5a5e58818c7584f784 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv @@ -1,42 +1,40 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,1 -,90,88,512,0,0,0,0,0,0,0,Target,0 -,91,90,256,0,89,0,0,0,0,0,Relations,1 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}" -,2,91,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,1, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" +,92,90,256,0,0,0,89,0,0,0,0,0,Relations,1, +,93,90,256,0,1,92,91,0,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 ,298,89,512,0,0,0,0,0,0,0,0,0,"Regular Element #2",1 -,299,91,256,0,0,0,298,0,0,0,0,0,"Regular Element #2",1 -,300,91,128,0,0,0,297,0,0,0,0,0,"Regular Element #1",2 +,299,92,256,0,0,0,298,0,0,0,0,0,"Regular Element #2",1 +,300,92,128,0,0,0,297,0,0,0,0,0,"Regular Element #1",2 tx_irretutorial_1nff_hotel ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,offers ,2,89,512,0,0,0,0,0,0,0,0,0,"Hotel #0",89,pages,,0 ,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,0 -,7,91,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 -,8,91,1,0,1,7,6,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",2,pages_language_overlay,,0 -,9,91,1,0,0,0,5,0,0,0,0,0,"Hotel #1",299,tt_content,,1 -,10,91,1,0,0,0,3,0,0,0,0,0,"Hotel #1",300,tt_content,,2 -,11,91,2,0,0,0,4,0,0,0,0,0,"Hotel #2",300,tt_content,,1 +,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",91,pages,,0 +,7,92,1,0,0,0,2,0,0,0,0,0,"Hotel #0",92,pages,,0 +,8,92,1,0,1,7,6,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",93,pages,,0 +,9,92,1,0,0,0,5,0,0,0,0,0,"Hotel #1",299,tt_content,,1 +,10,92,1,0,0,0,3,0,0,0,0,0,"Hotel #1",300,tt_content,,2 +,11,92,2,0,0,0,4,0,0,0,0,0,"Hotel #2",300,tt_content,,1 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 ,6,89,2,0,0,0,0,0,0,0,0,0,"Offer #1.2",3,tx_irretutorial_1nff_hotel,,2 ,7,89,1,0,0,0,0,0,0,0,0,0,"Offer #2.1",4,tx_irretutorial_1nff_hotel,,1 ,8,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",5,tx_irretutorial_1nff_hotel,,1 -,9,91,1,0,0,0,8,0,0,0,0,0,"Offer #1.1",9,tx_irretutorial_1nff_hotel,,1 -,10,91,1,0,0,0,5,0,0,0,0,0,"Offer #1.1",10,tx_irretutorial_1nff_hotel,,3 -,11,91,2,0,0,0,6,0,0,0,0,0,"Offer #1.2",10,tx_irretutorial_1nff_hotel,,2 -,12,91,1,0,0,0,7,0,0,0,0,0,"Offer #2.1",11,tx_irretutorial_1nff_hotel,,1 +,9,92,1,0,0,0,8,0,0,0,0,0,"Offer #1.1",9,tx_irretutorial_1nff_hotel,,1 +,10,92,1,0,0,0,5,0,0,0,0,0,"Offer #1.1",10,tx_irretutorial_1nff_hotel,,3 +,11,92,2,0,0,0,6,0,0,0,0,0,"Offer #1.2",10,tx_irretutorial_1nff_hotel,,2 +,12,92,1,0,0,0,7,0,0,0,0,0,"Offer #2.1",11,tx_irretutorial_1nff_hotel,,1 tx_irretutorial_1nff_price ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier ,7,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",5,tx_irretutorial_1nff_offer, @@ -46,10 +44,10 @@ tx_irretutorial_1nff_price ,11,89,2,0,0,0,0,0,0,0,0,0,"Price #1.2.2",6,tx_irretutorial_1nff_offer, ,12,89,1,0,0,0,0,0,0,0,0,0,"Price #2.1.1",7,tx_irretutorial_1nff_offer, ,13,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",8,tx_irretutorial_1nff_offer, -,14,91,1,0,0,0,13,0,0,0,0,0,"Price #1.1.1",9,tx_irretutorial_1nff_offer, -,15,91,1,0,0,0,7,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer, -,16,91,2,0,0,0,8,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer, -,17,91,3,0,0,0,9,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer, -,18,91,1,0,0,0,10,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer, -,19,91,2,0,0,0,11,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer, -,20,91,1,0,0,0,12,0,0,0,0,0,"Price #2.1.1",12,tx_irretutorial_1nff_offer, +,14,92,1,0,0,0,13,0,0,0,0,0,"Price #1.1.1",9,tx_irretutorial_1nff_offer, +,15,92,1,0,0,0,7,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer, +,16,92,2,0,0,0,8,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer, +,17,92,3,0,0,0,9,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer, +,18,92,1,0,0,0,10,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer, +,19,92,2,0,0,0,11,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer, +,20,92,1,0,0,0,12,0,0,0,0,0,"Price #2.1.1",12,tx_irretutorial_1nff_offer, diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageAddMonoglotHotelChildNCopyPageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageAddMonoglotHotelChildNCopyPageWSynchronization.csv index 12f915614868bb0cd76c413a2b75ad60fc547e54..be2da9bd0ce72c61129f89b03094c1034398c129 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageAddMonoglotHotelChildNCopyPageWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageAddMonoglotHotelChildNCopyPageWSynchronization.csv @@ -1,46 +1,44 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,2 -,90,88,512,0,0,0,0,0,0,0,Target,0 -,91,90,256,0,89,0,0,0,0,0,Relations,2 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}" -,2,91,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,2, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" +,92,90,256,0,0,0,89,0,0,0,0,0,Relations,2, +,93,90,256,0,1,92,91,0,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 ,298,89,512,0,0,0,0,0,0,0,0,0,"Regular Element #2",1 -,299,91,256,0,0,0,298,0,0,0,0,0,"Regular Element #2",1 -,300,91,128,0,0,0,297,0,0,0,0,0,"Regular Element #1",2 +,299,92,256,0,0,0,298,0,0,0,0,0,"Regular Element #2",1 +,300,92,128,0,0,0,297,0,0,0,0,0,"Regular Element #1",2 tx_irretutorial_1nff_hotel ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,offers ,2,89,1,0,0,0,0,0,0,0,0,0,"Hotel #0",89,pages,,0 ,3,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1792,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",1,pages_language_overlay,,0 +,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 ,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,pages,,0 -,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",1,pages_language_overlay,,0 -,9,91,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 -,10,91,2,0,0,0,7,0,0,0,0,0,"Hotel #007",91,pages,,0 -,11,91,1,0,0,0,6,0,0,0,0,0,"Hotel #0",2,pages_language_overlay,,0 -,12,91,2,0,0,0,8,0,0,0,0,0,"Hotel #007",2,pages_language_overlay,,0 -,13,91,1,0,0,0,5,0,0,0,0,0,"Hotel #1",299,tt_content,,1 -,14,91,1,0,0,0,3,0,0,0,0,0,"Hotel #1",300,tt_content,,2 -,15,91,2,0,0,0,4,0,0,0,0,0,"Hotel #2",300,tt_content,,1 +,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",91,pages,,0 +,9,92,1,0,0,0,2,0,0,0,0,0,"Hotel #0",92,pages,,0 +,10,92,2,0,0,0,7,0,0,0,0,0,"Hotel #007",92,pages,,0 +,11,92,1,0,0,0,6,0,0,0,0,0,"Hotel #0",93,pages,,0 +,12,92,2,0,0,0,8,0,0,0,0,0,"Hotel #007",93,pages,,0 +,13,92,1,0,0,0,5,0,0,0,0,0,"Hotel #1",299,tt_content,,1 +,14,92,1,0,0,0,3,0,0,0,0,0,"Hotel #1",300,tt_content,,2 +,15,92,2,0,0,0,4,0,0,0,0,0,"Hotel #2",300,tt_content,,1 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 ,6,89,2,0,0,0,0,0,0,0,0,0,"Offer #1.2",3,tx_irretutorial_1nff_hotel,,2 ,7,89,1,0,0,0,0,0,0,0,0,0,"Offer #2.1",4,tx_irretutorial_1nff_hotel,,1 ,8,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",5,tx_irretutorial_1nff_hotel,,1 -,9,91,1,0,0,0,8,0,0,0,0,0,"Offer #1.1",13,tx_irretutorial_1nff_hotel,,1 -,10,91,1,0,0,0,5,0,0,0,0,0,"Offer #1.1",14,tx_irretutorial_1nff_hotel,,3 -,11,91,2,0,0,0,6,0,0,0,0,0,"Offer #1.2",14,tx_irretutorial_1nff_hotel,,2 -,12,91,1,0,0,0,7,0,0,0,0,0,"Offer #2.1",15,tx_irretutorial_1nff_hotel,,1 +,9,92,1,0,0,0,8,0,0,0,0,0,"Offer #1.1",13,tx_irretutorial_1nff_hotel,,1 +,10,92,1,0,0,0,5,0,0,0,0,0,"Offer #1.1",14,tx_irretutorial_1nff_hotel,,3 +,11,92,2,0,0,0,6,0,0,0,0,0,"Offer #1.2",14,tx_irretutorial_1nff_hotel,,2 +,12,92,1,0,0,0,7,0,0,0,0,0,"Offer #2.1",15,tx_irretutorial_1nff_hotel,,1 tx_irretutorial_1nff_price ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier ,7,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",5,tx_irretutorial_1nff_offer, @@ -50,10 +48,10 @@ tx_irretutorial_1nff_price ,11,89,2,0,0,0,0,0,0,0,0,0,"Price #1.2.2",6,tx_irretutorial_1nff_offer, ,12,89,1,0,0,0,0,0,0,0,0,0,"Price #2.1.1",7,tx_irretutorial_1nff_offer, ,13,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",8,tx_irretutorial_1nff_offer, -,14,91,1,0,0,0,13,0,0,0,0,0,"Price #1.1.1",9,tx_irretutorial_1nff_offer, -,15,91,1,0,0,0,7,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer, -,16,91,2,0,0,0,8,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer, -,17,91,3,0,0,0,9,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer, -,18,91,1,0,0,0,10,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer, -,19,91,2,0,0,0,11,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer, -,20,91,1,0,0,0,12,0,0,0,0,0,"Price #2.1.1",12,tx_irretutorial_1nff_offer, +,14,92,1,0,0,0,13,0,0,0,0,0,"Price #1.1.1",9,tx_irretutorial_1nff_offer, +,15,92,1,0,0,0,7,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer, +,16,92,2,0,0,0,8,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer, +,17,92,3,0,0,0,9,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer, +,18,92,1,0,0,0,10,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer, +,19,92,2,0,0,0,11,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer, +,20,92,1,0,0,0,12,0,0,0,0,0,"Price #2.1.1",12,tx_irretutorial_1nff_offer, diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv index 30244615be741a125665380b4bd588c471825f29..015a731455f44cb6e47cd76acb6a9a9c719ecec4 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,2 -,90,88,512,0,0,0,0,0,0,0,Target,0 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2, +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,2, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 @@ -17,10 +15,10 @@ tx_irretutorial_1nff_hotel ,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1000000000,1,0,0,2,0,0,0,0,0,"Hotel #0",1,pages_language_overlay,,0 -,7,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",1,pages_language_overlay,,0 +,6,89,1000000000,1,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 +,7,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 ,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,pages,,0 -,9,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",1,pages_language_overlay,,0 +,9,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",91,pages,,0 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv index 065db2892ad4f524a8c8cf3b2bf97bbff30bf36a..db421d57a6d27bb52f1e3561aa6fc6944655e394 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,2 -,90,88,512,0,0,0,0,0,0,0,Target,0 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,2, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 @@ -17,9 +15,9 @@ tx_irretutorial_1nff_hotel ,3,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1792,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,0 +,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",91,pages,,0 ,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,pages,,0 -,8,89,2,0,1,7,0,0,0,0,0,0,"[Translate to Dansk:] Hotel #007",1,pages_language_overlay,,0 +,8,89,2,0,1,7,0,0,0,0,0,0,"[Translate to Dansk:] Hotel #007",91,pages,,0 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv index 7c07fb3126ec9e059b1fccaf96cb97ffe33600ac..8bc243932a149c0a8726f69b4459f3c51d089b3d 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,2 -,90,88,512,0,0,0,0,0,0,0,Target,0 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,2, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 @@ -17,9 +15,9 @@ tx_irretutorial_1nff_hotel ,3,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1792,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",1,pages_language_overlay,,0 +,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 ,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,pages,,0 -,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",1,pages_language_overlay,,0 +,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",91,pages,,0 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv index 0fee9b8cdfcb0fd77061d9aed07dff819c80fbdf..4415b18be91e8e4b20551238882a95e308fe8c16 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,1 -,90,88,512,0,0,0,0,0,0,0,Target,0 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1, +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0 +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0 +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,1 +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0 +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",1 tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 @@ -17,7 +15,7 @@ tx_irretutorial_1nff_hotel ,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",1,pages_language_overlay,,0 +,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv index 3ab8e50f4cc8160624d6c547b64ba9122dd30894..e4af05dfa80f17da8d9558d0aad7d1d6d01f7b43 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels -,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0 -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0 -,89,88,256,0,0,0,0,0,0,0,Relations,1 -,90,88,512,0,0,0,0,0,0,0,Target,0 -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_hotels,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest,0, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest,0, +,89,88,256,0,0,0,0,0,0,0,0,0,Relations,1, +,90,88,512,0,0,0,0,0,0,0,0,0,Target,0, +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent"",""tx_irretutorial_hotels"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1nff_hotels ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2 @@ -17,7 +15,7 @@ tx_irretutorial_1nff_hotel ,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2 ,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1 ,5,89,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1 -,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,0 +,6,89,1,0,1,2,2,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",91,pages,,0 tx_irretutorial_1nff_offer ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,prices ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3 diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php index cdabe46de66e99721eea9830a3098ebb9bb25605..613086af702f108a45b355537a19b33f1b4b60f3 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php @@ -32,7 +32,6 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D const VALUE_LanguageIdSecond = 2; const TABLE_Page = 'pages'; - const TABLE_PageOverlay = 'pages_language_overlay'; const TABLE_Content = 'tt_content'; /** @@ -305,17 +304,22 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D */ public function localizePage() { + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; } public function localizePageWithLanguageSynchronization() { - $GLOBALS['TCA']['pages_language_overlay']['columns']['title']['config']['behaviour']['allowLanguageSynchronization'] = true; + unset($GLOBALS['TCA'][self::TABLE_Page]['columns']['title']['l10n_mode']); + $GLOBALS['TCA'][self::TABLE_Page]['columns']['title']['config']['behaviour']['allowLanguageSynchronization'] = true; + // in these test cases we expect new pages not to be hidden in order to + // verify proper overlaying behavior during the frontend render process + $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0; $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId); $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId]; - $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId]; $this->actionService->modifyRecord(self::TABLE_Page, self::VALUE_PageId, ['title' => 'Testing #1']); } diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/DataSet/LiveDefaultPages.csv b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/DataSet/LiveDefaultPages.csv index 335d96c767647fc81f7bea214ce03bf8e7c5ca38..2e47970e493b22127d833ddee20816cc305a6b6b 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/DataSet/LiveDefaultPages.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/DataSet/LiveDefaultPages.csv @@ -1,6 +1,6 @@ "pages",,,,,,,,,,, -,"uid","pid","sorting","deleted","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title" -,1,0,256,0,0,0,0,0,0,0,"FunctionalTest" -,88,1,256,0,0,0,0,0,0,0,"DataHandlerTest" -,89,88,256,0,0,0,0,0,0,0,"Relations" -,90,88,512,0,0,0,0,0,0,0,"Target" +,"uid","pid","sorting","deleted","sys_language_uid","l10n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title" +,1,0,256,0,0,0,0,0,0,0,0,0,"FunctionalTest" +,88,1,256,0,0,0,0,0,0,0,0,0,"DataHandlerTest" +,89,88,256,0,0,0,0,0,0,0,0,0,"Relations" +,90,88,512,0,0,0,0,0,0,0,0,0,"Target" diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPage.csv b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPage.csv index 8a03b53e27dfdbde7012ea5e95c5fb538ca20ca9..0d823f1bac03893a74a956a94e9fe26c0c3104ff 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPage.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPage.csv @@ -1,14 +1,12 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,Relations -,90,88,512,0,0,0,0,0,0,0,Target -,91,90,256,0,89,0,0,0,0,0,Relations -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations" -,2,91,0,1,0,0,0,0,"[Translate to Dansk:] Relations" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,Relations +,90,88,512,0,0,0,0,0,0,0,0,0,Target +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations" +,92,90,256,0,0,0,89,0,0,0,0,0,Relations +,93,90,256,0,1,92,91,0,0,0,0,0,"[Translate to Dansk:] Relations" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" @@ -18,9 +16,9 @@ tt_content ,300,89,1024,0,1,299,299,299,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" ,301,89,384,0,1,297,297,297,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" ,302,89,448,0,2,297,301,301,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" -,303,91,256,0,0,0,0,299,0,0,0,0,0,"Regular Element #3" -,304,91,128,0,1,303,303,300,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" -,305,91,64,0,0,0,0,298,0,0,0,0,0,"Regular Element #2" -,306,91,32,0,0,0,0,297,0,0,0,0,0,"Regular Element #1" -,307,91,16,0,1,306,306,301,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" -,308,91,8,0,2,306,307,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,303,92,256,0,0,0,0,299,0,0,0,0,0,"Regular Element #3" +,304,92,128,0,1,303,303,300,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" +,305,92,64,0,0,0,0,298,0,0,0,0,0,"Regular Element #2" +,306,92,32,0,0,0,0,297,0,0,0,0,0,"Regular Element #1" +,307,92,16,0,1,306,306,301,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" +,308,92,8,0,2,306,307,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPageWSynchronization.csv index fb115f6bde7bd4602afff4d13b42ea520cb7538a..c259294fe49ac0432de6bf0ca34e9b6de3a96024 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPageWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizeNCopyPageWSynchronization.csv @@ -1,14 +1,12 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,"Testing #1" -,90,88,512,0,0,0,0,0,0,0,Target -,91,90,256,0,89,0,0,0,0,0,"Testing #1" -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,l10n_state -,1,89,0,1,0,0,0,0,"Testing #1","{""title"":""parent""}" -,2,91,0,1,0,0,0,0,"Testing #1","{""title"":""parent""}" +,uid,pid,sorting,sys_language_uid,l10n_parent,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest, +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest, +,89,88,256,0,0,0,0,0,0,0,0,0,"Testing #1", +,90,88,512,0,0,0,0,0,0,0,0,0,Target, +,91,88,256,1,89,0,0,0,0,0,0,0,"Testing #1","{""title"":""parent"",""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent""}" +,92,90,256,0,0,0,89,0,0,0,0,0,"Testing #1", +,93,90,256,1,92,0,91,0,0,0,0,0,"Testing #1","{""title"":""parent"",""url"":""parent"",""lastUpdated"":""parent"",""newUntil"":""parent"",""no_search"":""parent"",""shortcut"":""parent"",""shortcut_mode"":""parent"",""author"":""parent"",""author_email"":""parent"",""media"":""parent""}" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" @@ -18,9 +16,9 @@ tt_content ,300,89,1024,0,1,299,299,299,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" ,301,89,384,0,1,297,297,297,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" ,302,89,448,0,2,297,301,301,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" -,303,91,256,0,0,0,0,299,0,0,0,0,0,"Regular Element #3" -,304,91,128,0,1,303,303,300,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" -,305,91,64,0,0,0,0,298,0,0,0,0,0,"Regular Element #2" -,306,91,32,0,0,0,0,297,0,0,0,0,0,"Regular Element #1" -,307,91,16,0,1,306,306,301,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" -,308,91,8,0,2,306,307,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,303,92,256,0,0,0,0,299,0,0,0,0,0,"Regular Element #3" +,304,92,128,0,1,303,303,300,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3" +,305,92,64,0,0,0,0,298,0,0,0,0,0,"Regular Element #2" +,306,92,32,0,0,0,0,297,0,0,0,0,0,"Regular Element #1" +,307,92,16,0,1,306,306,301,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1" +,308,92,8,0,2,306,307,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv index f78fb3a65eb9b89f0aa370fce6983144d7a5ff8d..a4e9444fc118fa8b0b168d5b1d03c868078f6dbe 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,Relations -,90,88,512,0,0,0,0,0,0,0,Target -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations" +,uid,pid,sorting,sys_language_uid,l10n_parent,deleted,hidden,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,0,Relations +,90,88,512,0,0,0,0,0,0,0,0,0,0,Target +,91,88,256,1,89,0,0,0,0,0,0,0,0,"[Translate to Dansk:] Relations" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePageWSynchronization.csv index aca0204998d87239aef4886bc46addda920fa2ba..80d56cb4231750e164458a3a5b4d674c8d275775 100644 --- a/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePageWSynchronization.csv +++ b/typo3/sysext/core/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePageWSynchronization.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,"Testing #1" -,90,88,512,0,0,0,0,0,0,0,Target -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,0,0,0,0,"Testing #1" +,uid,pid,sorting,deleted,l10n_parent,sys_language_uid,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,"Testing #1" +,90,88,512,0,0,0,0,0,0,0,0,0,Target +,91,88,256,0,89,1,0,0,0,0,0,0,"Testing #1" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/Overrides/pages_language_overlay.php b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/Overrides/pages_language_overlay.php deleted file mode 100644 index 96284dbc3236e8f2cf152644735072b1df52c7ac..0000000000000000000000000000000000000000 --- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/Configuration/TCA/Overrides/pages_language_overlay.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns( - 'pages_language_overlay', - [ - 'tx_irretutorial_hotels' => [ - 'exclude' => true, - 'label' => 'LLL:EXT:irre_tutorial/Resources/Private/Language/locallang_db.xml:pages.tx_irretutorial_hotels', - 'config' => [ - 'type' => 'inline', - 'foreign_table' => 'tx_irretutorial_1nff_hotel', - 'foreign_field' => 'parentid', - 'foreign_table_field' => 'parenttable', - 'maxitems' => 10, - 'appearance' => [ - 'showSynchronizationLink' => 1, - 'showAllLocalizationLink' => 1, - 'showPossibleLocalizationRecords' => 1, - 'showRemovedLocalizationRecords' => 1, - ], - ] - ], - ] -); - -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( - 'pages_language_overlay', - '--div--;LLL:EXT:irre_tutorial/Resources/Private/Language/locallang_db.xml:pages.doktype.div.irre, tx_irretutorial_hotels' -); diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_tables.sql b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_tables.sql index b2fb61d06f732adc3542876cb09b8e2a02012924..763c88e3672504a89dfb9a18ba3239f78516c076 100644 --- a/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_tables.sql +++ b/typo3/sysext/core/Tests/Functional/Fixtures/Extensions/irre_tutorial/ext_tables.sql @@ -9,15 +9,6 @@ CREATE TABLE pages ( tx_irretutorial_hotels int(11) DEFAULT '0' NOT NULL ); - -# -# Table structure for table 'pages_language_overlay' -# -CREATE TABLE pages_language_overlay ( - tx_irretutorial_hotels int(11) DEFAULT '0' NOT NULL -); - - # # Table structure for table 'tt_content' # diff --git a/typo3/sysext/core/Tests/Functional/Fixtures/pages_language_overlay.xml b/typo3/sysext/core/Tests/Functional/Fixtures/pages_language_overlay.xml deleted file mode 100644 index a85fc9a1f5af62549128b9f10112d407ac85c140..0000000000000000000000000000000000000000 --- a/typo3/sysext/core/Tests/Functional/Fixtures/pages_language_overlay.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<dataset> - <pages_language_overlay> - <uid>1</uid> - <pid>1</pid> - <title>Root [Dansk]</title> - <deleted>0</deleted> - <hidden>0</hidden> - <sys_language_uid>1</sys_language_uid> - </pages_language_overlay> - <pages_language_overlay> - <uid>2</uid> - <pid>1</pid> - <title>Root [Deutsch]</title> - <deleted>0</deleted> - <hidden>0</hidden> - <sys_language_uid>2</sys_language_uid> - </pages_language_overlay> -</dataset> \ No newline at end of file diff --git a/typo3/sysext/core/Tests/Unit/Database/Schema/Fixtures/tablebuilder.sql b/typo3/sysext/core/Tests/Unit/Database/Schema/Fixtures/tablebuilder.sql index d542c72b8bbaca8f6df8294a642eb0d6570f062e..558465bc939b45c7d7c4c95b8fa4bb95e9257910 100644 --- a/typo3/sysext/core/Tests/Unit/Database/Schema/Fixtures/tablebuilder.sql +++ b/typo3/sysext/core/Tests/Unit/Database/Schema/Fixtures/tablebuilder.sql @@ -17,5 +17,5 @@ CREATE TABLE aTestTable ( UNIQUE `parent` (pid,`deleted`,sorting), KEY noCache (`no_cache`), KEY substring (TSconfig(80)), - FOREIGN KEY fk_overlay (uid) REFERENCES pages_language_overlay(pid) + FOREIGN KEY fk_overlay (uid) REFERENCES any_foreign_table(pid) ) ENGINE = MyISAM DEFAULT CHARACTER SET latin1 COLLATE latin1_german_cs ROW_FORMAT DYNAMIC AUTO_INCREMENT=1; diff --git a/typo3/sysext/core/Tests/Unit/Database/Schema/Parser/TableBuilderTest.php b/typo3/sysext/core/Tests/Unit/Database/Schema/Parser/TableBuilderTest.php index 825feb31953051d678f6cefb8b7a138d4281c6ed..f2e2996c956e808ad2272e709d1250f85b5fbdd6 100644 --- a/typo3/sysext/core/Tests/Unit/Database/Schema/Parser/TableBuilderTest.php +++ b/typo3/sysext/core/Tests/Unit/Database/Schema/Parser/TableBuilderTest.php @@ -242,7 +242,7 @@ class TableBuilderTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase $this->assertSame(['`pid`'], $subject->getForeignColumns()); $this->assertSame(['`uid`'], $subject->getLocalColumns()); $this->assertSame('aTestTable', $subject->getLocalTableName()); - $this->assertSame('pages_language_overlay', $subject->getForeignTableName()); + $this->assertSame('any_foreign_table', $subject->getForeignTableName()); } /** diff --git a/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php b/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php index 0b989724529a49b0f4ade2e8783ee5083fc09d95..4879e426171cb7f3fcc1f30bb16e809b89d56b68 100644 --- a/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php +++ b/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php @@ -2160,7 +2160,6 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'config' => [ 'type' => 'input', ], - 'l10n_mode' => 'any-possible-value', ], ], ], @@ -2170,21 +2169,13 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'config' => [ 'type' => 'input', ], + 'l10n_mode' => 'any-possible-value', ], ], ], ], [ 'pages' => [ - 'columns' => [ - 'aColumn' => [ - 'config' => [ - 'type' => 'input', - ], - ], - ], - ], - 'pages_language_overlay' => [ 'columns' => [ 'aColumn' => [ 'config' => [ @@ -2203,9 +2194,6 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'aColumn' => [ 'config' => [ 'type' => 'input', - 'behaviour' => [ - 'allowLanguageSynchronization' => true, - ] ], ], ], @@ -2215,6 +2203,9 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'aColumn' => [ 'config' => [ 'type' => 'input', + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ] ], ], ], @@ -2222,16 +2213,6 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase ], [ 'pages' => [ - 'columns' => [ - 'aColumn' => [ - 'config' => [ - 'type' => 'input', - 'behaviour' => [] - ], - ], - ], - ], - 'pages_language_overlay' => [ 'columns' => [ 'aColumn' => [ 'config' => [ @@ -2269,15 +2250,6 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase 'aColumn' => [], ], ], - 'pages_language_overlay' => [ - 'columns' => [ - 'aColumn' => [ - 'config' => [ - 'type' => 'input', - ], - ], - ], - ], ] ], 'superfluous allowLanguageSynchronization' => [ @@ -2302,16 +2274,12 @@ class TcaMigrationTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase ], [ 'pages' => [ - 'columns' => [ - 'aColumn' => [], - ], - ], - 'pages_language_overlay' => [ 'columns' => [ 'aColumn' => [ 'config' => [ - 'type' => 'input', - 'behaviour' => [] + 'behaviour' => [ + 'allowLanguageSynchronization' => true, + ] ], ], ], diff --git a/typo3/sysext/core/ext_tables.php b/typo3/sysext/core/ext_tables.php index aecd9b88265f7cd922ba86f356e0377fe8613114..ece80f7b72a34ec66abb54ff31ee1f8f58d4fc17 100644 --- a/typo3/sysext/core/ext_tables.php +++ b/typo3/sysext/core/ext_tables.php @@ -95,7 +95,6 @@ $GLOBALS['TBE_STYLES'] = []; * documentation found in "Inside TYPO3" */ \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('pages', 'EXT:core/Resources/Private/Language/locallang_csh_pages.xlf'); -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('pages_language_overlay', 'EXT:core/Resources/Private/Language/locallang_csh_pageslol.xlf'); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('be_users', 'EXT:core/Resources/Private/Language/locallang_csh_be_users.xlf'); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('be_groups', 'EXT:core/Resources/Private/Language/locallang_csh_be_groups.xlf'); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('sys_filemounts', 'EXT:core/Resources/Private/Language/locallang_csh_sysfilem.xlf'); diff --git a/typo3/sysext/core/ext_tables.sql b/typo3/sysext/core/ext_tables.sql index 45373b0c2107c0d3d9f03420a319b6f74a370215..8b3e06402717c87fd29d4a2be82bb03e9a8fa996 100644 --- a/typo3/sysext/core/ext_tables.sql +++ b/typo3/sysext/core/ext_tables.sql @@ -116,6 +116,10 @@ CREATE TABLE pages ( editlock tinyint(4) unsigned DEFAULT '0' NOT NULL, crdate int(11) unsigned DEFAULT '0' NOT NULL, cruser_id int(11) unsigned DEFAULT '0' NOT NULL, + sys_language_uid int(11) unsigned DEFAULT '0' NOT NULL, + l10n_parent int(11) DEFAULT '0' NOT NULL, + l10n_source int(11) DEFAULT '0' NOT NULL, + l10n_diffsource mediumblob, hidden tinyint(4) unsigned DEFAULT '0' NOT NULL, title varchar(255) DEFAULT '' NOT NULL, doktype int(11) unsigned DEFAULT '0' NOT NULL, @@ -156,6 +160,7 @@ CREATE TABLE pages ( backend_layout varchar(64) DEFAULT '' NOT NULL, backend_layout_next_level varchar(64) DEFAULT '' NOT NULL, tsconfig_includes text, + legacy_overlay_uid int(11) unsigned DEFAULT '0' NOT NULL, PRIMARY KEY (uid), KEY t3ver_oid (t3ver_oid,t3ver_wsid), KEY parent (pid,deleted,sorting), diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php index d43a3bd3bcc83aa5b4bf2b78ae9cbb16f2a96db2..857a9271d9f9ac1d9589b93fc3cb07ed2a3d3adc 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php @@ -591,7 +591,6 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface if (isset($tableName) && isset($GLOBALS['TCA'][$tableName]) && isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && isset($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']) - && $tableName !== 'pages_language_overlay' ) { if (isset($row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']]) && $row[$GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']] > 0 @@ -623,7 +622,6 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface $row = $pageRepository->getPageOverlay($row, $querySettings->getLanguageUid()); } elseif (isset($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && $GLOBALS['TCA'][$tableName]['ctrl']['languageField'] !== '' - && $tableName !== 'pages_language_overlay' ) { if (in_array($row[$GLOBALS['TCA'][$tableName]['ctrl']['languageField']], [-1, 0])) { $overlayMode = $querySettings->getLanguageMode() === 'strict' ? 'hideNonTranslated' : ''; diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php index 43d568956aa099700d4642fa74a89e6d4c23de5b..6c7e341e00283877b84992b850af373c8af70b9b 100644 --- a/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php +++ b/typo3/sysext/extbase/Tests/Functional/Persistence/TranslatedContentTest.php @@ -210,7 +210,7 @@ class TranslatedContentTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandlin } /** - * Dutch language has pages_language_overlay record and some content elements are translated + * Dutch language has pages record and some content elements are translated * * @return array */ diff --git a/typo3/sysext/filelist/Classes/FileList.php b/typo3/sysext/filelist/Classes/FileList.php index 35ec4b8f918300316c064524ddd193a6e3774552..0ccac54c493f8906a5d2c0572926e487d1a9ec49 100644 --- a/typo3/sysext/filelist/Classes/FileList.php +++ b/typo3/sysext/filelist/Classes/FileList.php @@ -752,17 +752,17 @@ class FileList { // Look up page overlays: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder ->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->andX( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->gt( 'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) diff --git a/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php index 000f9190eab695a0fbda57b2403f920dc9a8f1b1..0f78ecbb5b2fe2ab0e074d843e527d11a1c0eab1 100644 --- a/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php +++ b/typo3/sysext/frontend/Classes/ContentObject/Menu/AbstractMenuContentObject.php @@ -1286,7 +1286,7 @@ abstract class AbstractMenuContentObject if ($languageUid && ($this->conf['protectLvar'] === 'all' || GeneralUtility::hideIfNotTranslated($data['l18n_cfg']))) { $olRec = $tsfe->sys_page->getPageOverlay($data['uid'], $languageUid); if (empty($olRec)) { - // If no pages_language_overlay record then page can NOT be accessed in + // If no page translation record then page can NOT be accessed in // the language pointed to by "&L" and therefore we protect the link by setting "&L=0" $data['_ADD_GETVARS'] .= '&L=0'; } diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php index f580b40d78768183a1166c5b120247a1fa8f5069..a24ab68586e21528bbdbf13849387197e4d5ceeb 100644 --- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php +++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php @@ -263,7 +263,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface /** * Flag indicating that hidden records should be shown. This includes - * sys_template, pages_language_overlay and even fe_groups in addition to all + * sys_template and even fe_groups in addition to all * other regular content. So in effect, this includes everything except pages. * @var bool */ diff --git a/typo3/sysext/frontend/Classes/Page/PageRepository.php b/typo3/sysext/frontend/Classes/Page/PageRepository.php index 78ebcc84f1964892a3d5829fe9240cb83fbd546f..abaa43274305131d34a1a0c01c6a1d9f5cbc18dc 100644 --- a/typo3/sysext/frontend/Classes/Page/PageRepository.php +++ b/typo3/sysext/frontend/Classes/Page/PageRepository.php @@ -460,19 +460,19 @@ class PageRepository implements LoggerAwareInterface } // NOTE regarding the query restrictions // Currently the showHiddenRecords of TSFE set will allow - // pages_language_overlay records to be selected as they are + // page translation records to be selected as they are // child-records of a page. // However you may argue that the showHiddenField flag should // determine this. But that's not how it's done right now. // Selecting overlay record: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); $result = $queryBuilder->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->in( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($page_ids, Connection::PARAM_INT_ARRAY) ), $queryBuilder->expr()->eq( @@ -484,12 +484,12 @@ class PageRepository implements LoggerAwareInterface $overlays = []; while ($row = $result->fetch()) { - $this->versionOL('pages_language_overlay', $row); + $this->versionOL('pages', $row); if (is_array($row)) { $row['_PAGES_OVERLAY'] = true; $row['_PAGES_OVERLAY_UID'] = $row['uid']; $row['_PAGES_OVERLAY_LANGUAGE'] = $lUid; - $origUid = $row['pid']; + $origUid = $row['l10n_parent']; // Unset vital fields that are NOT allowed to be overlaid: unset($row['uid']); unset($row['pid']); @@ -545,7 +545,7 @@ class PageRepository implements LoggerAwareInterface if ($GLOBALS['TCA'][$table] && $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) { // Return record for ALL languages untouched // TODO: Fix call stack to prevent this situation in the first place - if ($table !== 'pages_language_overlay' && (int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] !== -1) { + if ((int)$row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] !== -1) { // Will not be able to work with other tables (Just didn't implement it yet; // Requires a scan over all tables [ctrl] part for first FIND the table that // carries localization information for this table (which could even be more @@ -703,6 +703,10 @@ class PageRepository implements LoggerAwareInterface $relationField, $queryBuilder->createNamedParameter($pageIds, Connection::PARAM_INT_ARRAY) ), + $queryBuilder->expr()->eq( + 'sys_language_uid', + $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) + ), QueryHelper::stripLogicalOperatorPrefix($this->where_hid_del), QueryHelper::stripLogicalOperatorPrefix($this->where_groupAccess), QueryHelper::stripLogicalOperatorPrefix($additionalWhereClause) @@ -1301,7 +1305,7 @@ class PageRepository implements LoggerAwareInterface if ($show_hidden === -1 && is_object($this->getTypoScriptFrontendController())) { // If show_hidden was not set from outside and if TSFE is an object, set it // based on showHiddenPage and showHiddenRecords from TSFE - $show_hidden = $table === 'pages' || $table === 'pages_language_overlay' + $show_hidden = $table === 'pages' ? $this->getTypoScriptFrontendController()->showHiddenPage : $this->getTypoScriptFrontendController()->showHiddenRecords; } @@ -1849,18 +1853,9 @@ class PageRepository implements LoggerAwareInterface $localizedId = $element['_PAGES_OVERLAY_UID']; } - if ($tableName === 'pages') { - $tableName = 'pages_language_overlay'; - } - $isTableLocalizable = ( !empty($GLOBALS['TCA'][$tableName]['ctrl']['languageField']) && !empty($GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField']) - // Only fetch references if the field is defined in TCA. This is a special use-case - // for pages_language_overlay because it may be possible that a field is defined in TCA - // of "pages" but not in "pages_language_overlay". Once pages_language_overlay is removed - // this check can be removed as well - && isset($GLOBALS['TCA'][$tableName]['columns'][$fieldName]) ); if ($isTableLocalizable && $localizedId !== null) { $localizedReferences = $fileRepository->findByRelation($tableName, $fieldName, $localizedId); diff --git a/typo3/sysext/frontend/Classes/View/AdminPanelView.php b/typo3/sysext/frontend/Classes/View/AdminPanelView.php index d5e768390eeafc7bbf2303fefbee17e711a644e1..eafc752a260c414e1a95bbd4090d91717f994698 100644 --- a/typo3/sysext/frontend/Classes/View/AdminPanelView.php +++ b/typo3/sysext/frontend/Classes/View/AdminPanelView.php @@ -963,14 +963,14 @@ class AdminPanelView // Edit Page Overlay if ($perms & Permission::PAGE_EDIT && $tsfe->sys_language_uid && $langAllowed) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); $row = $queryBuilder ->select('uid', 'pid', 't3ver_state') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->eq( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( @@ -981,12 +981,12 @@ class AdminPanelView ->setMaxResults(1) ->execute() ->fetch(); - $tsfe->sys_page->versionOL('pages_language_overlay', $row); + $tsfe->sys_page->versionOL('pages', $row); if (is_array($row)) { $link = BackendUtility::getModuleUrl( 'record_edit', [ - 'edit[pages_language_overlay][' . $row['uid'] . ']' => 'edit', + 'edit[pages][' . $row['uid'] . ']' => 'edit', 'noView' => 1, 'returnUrl' => $returnUrl ] diff --git a/typo3/sysext/frontend/Configuration/TCA/pages_language_overlay.php b/typo3/sysext/frontend/Configuration/TCA/pages_language_overlay.php index e8fbe58adc77937ee3a5747972ff1fbcae2c85a0..a5a8870c61d40c3f01ef98ae21b5e65bdd8dc7b3 100644 --- a/typo3/sysext/frontend/Configuration/TCA/pages_language_overlay.php +++ b/typo3/sysext/frontend/Configuration/TCA/pages_language_overlay.php @@ -24,6 +24,10 @@ return [ 'typeicon_classes' => [ 'default' => 'mimetypes-x-content-page-language-overlay' ], + // disabled until all migration has been done + 'hideTable' => true, + // This option needs to be set to the record is not shown in the be_groups ACLs + 'adminOnly' => true, 'searchFields' => 'title,subtitle,nav_title,keywords,description,abstract,author,author_email,url' ], 'interface' => [ @@ -68,7 +72,6 @@ return [ ] ], 'title' => [ - 'l10n_mode' => 'prefixLangTitle', 'label' => $GLOBALS['TCA']['pages']['columns']['title']['label'], 'config' => [ 'type' => 'input', diff --git a/typo3/sysext/frontend/Tests/Functional/Fixtures/pages.xml b/typo3/sysext/frontend/Tests/Functional/Fixtures/pages.xml index ff8cb0c32f37505ef00b8fccfb18f3f1551f7e5c..abb60ee80448ac1724e71a849e096857a3edb935 100644 --- a/typo3/sysext/frontend/Tests/Functional/Fixtures/pages.xml +++ b/typo3/sysext/frontend/Tests/Functional/Fixtures/pages.xml @@ -95,47 +95,53 @@ <perms_everybody>15</perms_everybody> </pages> - <pages_language_overlay> + <pages> <uid>901</uid> - <pid>1</pid> + <pid>0</pid> + <l10n_parent>1</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Wurzel 1</title> <deleted>0</deleted> - </pages_language_overlay> - <pages_language_overlay> + </pages> + <pages> <uid>902</uid> - <pid>2</pid> + <pid>1</pid> + <l10n_parent>2</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Attrappe 1-2</title> <deleted>0</deleted> - </pages_language_overlay> - <pages_language_overlay> + </pages> + <pages> <uid>903</uid> - <pid>3</pid> + <pid>1</pid> + <l10n_parent>3</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Attrappe 1-3</title> <deleted>0</deleted> - </pages_language_overlay> - <pages_language_overlay> + </pages> + <pages> <uid>904</uid> - <pid>5</pid> + <pid>2</pid> + <l10n_parent>5</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Attrappe 1-2-5</title> <deleted>0</deleted> - </pages_language_overlay> - <pages_language_overlay> + </pages> + <pages> <uid>905</uid> - <pid>6</pid> + <pid>2</pid> + <l10n_parent>6</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Attrappe 1-2-6</title> <deleted>0</deleted> - </pages_language_overlay> - <pages_language_overlay> + </pages> + <pages> <uid>906</uid> - <pid>9</pid> + <pid>3</pid> + <l10n_parent>9</l10n_parent> <sys_language_uid>1</sys_language_uid> <title>Attrappe 1-3-9</title> <deleted>0</deleted> - </pages_language_overlay> + </pages> </dataset> diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv b/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv index 68c32a7fe68ee3dc95d77a35ac41875e6ac7f553..b7383af8cd6a9c335e3cac95990afaf2b65be535 100644 --- a/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv +++ b/typo3/sysext/frontend/Tests/Functional/Rendering/DataSet/LiveDefaultPages.csv @@ -1,9 +1,7 @@ -pages,,,,,,,,,,, -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,Root page -,88,1,256,0,0,0,0,0,0,0,Subpage -,89,88,256,0,0,0,0,0,0,0,Default language Page -pages_language_overlay,,,,,,,,,,, -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,l10n_state, -,1,89,0,1,0,0,0,0,[DK]Page,"{""title"":""parent""}", -,2,89,0,3,0,0,0,0,[PL]Page,"{""title"":""parent""}", +pages,,,,,,,,,,,,,, +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,l10n_state +,1,0,256,0,0,0,0,0,0,0,0,0,Root page,"{}" +,88,1,256,0,0,0,0,0,0,0,0,0,Subpage,"{}" +,89,88,256,0,0,0,0,0,0,0,0,0,Default language Page,"{}" +,90,88,256,0,1,89,0,0,0,0,0,0,[DK]Page,"{""title"":""parent""}" +,91,88,256,0,3,89,0,0,0,0,0,0,[PL]Page,"{""title"":""parent""}" diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php index fa171f6458244f34a6d25b42df519a44bff1601f..c58ba16621469213cfb508430e96c76059ecabf5 100644 --- a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php +++ b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedContentRenderingTest.php @@ -36,7 +36,7 @@ use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\Response; * to that value) or "ignore" (just render the page and the content as this translation would exist). * When set to "0" or not set "", this means that the page request is using the default language for content * and page properties. - * Content fallback is evaluated on page level, not on the CE level. So it only makes a difference when the pages_language_overlay + * Content fallback is evaluated on page level, not on the CE level. So it only makes a difference when the page translation * for the requested language does not exist. * * config.sys_language_overlay = [0, 1, hideNonTranslated] @@ -272,7 +272,7 @@ class LocalizedContentRenderingTest extends \TYPO3\CMS\Core\Tests\Functional\Dat } /** - * Dutch language has pages_language_overlay record and some content elements are translated + * Dutch language has page translation record and some content elements are translated * * @return array */ diff --git a/typo3/sysext/frontend/Tests/Functional/Tca/PagesLanguageOverlayVisibleFieldsTest.php b/typo3/sysext/frontend/Tests/Functional/Tca/PagesLanguageOverlayVisibleFieldsTest.php index d5a84fe9cad9fe25de2c2fc72be767dea132d445..7c570fad82ff76be2cb6b3c3d7169e7ebf988aaf 100644 --- a/typo3/sysext/frontend/Tests/Functional/Tca/PagesLanguageOverlayVisibleFieldsTest.php +++ b/typo3/sysext/frontend/Tests/Functional/Tca/PagesLanguageOverlayVisibleFieldsTest.php @@ -166,7 +166,7 @@ class PagesLanguageOverlayVisibleFieldsTest extends \TYPO3\TestingFramework\Core $GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageService::class); $formEngineTestService = GeneralUtility::makeInstance(FormTestService::class); - $formResult = $formEngineTestService->createNewRecordForm('pages_language_overlay', ['doktype' => $doktype]); + $formResult = $formEngineTestService->createNewRecordForm('pages', ['doktype' => $doktype]); foreach ($expectedFields as $expectedField) { $this->assertNotFalse( diff --git a/typo3/sysext/frontend/ext_tables.php b/typo3/sysext/frontend/ext_tables.php index e8a4cdca6cc0b1529ef1972dd9438b9b1645a7b0..63a983fc1713298a7544db9f62ba2094ac19e404 100644 --- a/typo3/sysext/frontend/ext_tables.php +++ b/typo3/sysext/frontend/ext_tables.php @@ -2,7 +2,7 @@ defined('TYPO3_MODE') or die(); // Add allowed records to pages -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('pages_language_overlay,tt_content,sys_template,sys_domain,backend_layout'); +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::allowTableOnStandardPages('tt_content,sys_template,sys_domain,backend_layout'); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('_MOD_web_layout', 'EXT:frontend/Resources/Private/Language/locallang_csh_weblayout.xlf'); \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addLLrefForTCAdescr('fe_groups', 'EXT:frontend/Resources/Private/Language/locallang_csh_fe_groups.xlf'); diff --git a/typo3/sysext/info/Classes/Controller/TranslationStatusController.php b/typo3/sysext/info/Classes/Controller/TranslationStatusController.php index 7ab573527b43546da6f758517dc202078162ec17..84fef815a37a4ae30c1bebe5556ed6d0a42ed113 100644 --- a/typo3/sysext/info/Classes/Controller/TranslationStatusController.php +++ b/typo3/sysext/info/Classes/Controller/TranslationStatusController.php @@ -34,12 +34,6 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc */ protected $iconFactory; - /** - * @var string - * static table for pages_language_overlay - */ - protected static $pageLanguageOverlayTable = 'pages_language_overlay'; - /** * Construct for initialize class variables */ @@ -206,7 +200,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc if (is_array($row)) { $langRecUids[$langRow['uid']][] = $row['uid']; $status = $row['_HIDDEN'] ? (GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || GeneralUtility::hideIfDefaultLanguage($data['row']['l18n_cfg']) ? 'danger' : '') : 'success'; - $icon = $this->iconFactory->getIconForRecord('pages_language_overlay', $row, Icon::SIZE_SMALL)->render(); + $icon = $this->iconFactory->getIconForRecord('pages', $row, Icon::SIZE_SMALL)->render(); $info = $icon . htmlspecialchars( GeneralUtility::fixed_lgd_cs($row['title'], $titleLen) ) . ((string)$row['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars( @@ -224,7 +218,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc // Create links: $editUrl = BackendUtility::getModuleUrl('record_edit', [ 'edit' => [ - 'pages_language_overlay' => [ + 'pages' => [ $row['uid'] => 'edit' ] ], @@ -253,7 +247,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc +(document.webinfoForm[' . GeneralUtility::quoteJSvalue('newOL[' . $langRow['uid'] . '][' . $data['row']['uid'] . ']') . '].checked ? ' - . GeneralUtility::quoteJSvalue('&edit[pages_language_overlay][' . $data['row']['uid'] . ']=new') + . GeneralUtility::quoteJSvalue('&edit[pages][' . $data['row']['uid'] . ']=new') . ' : \'\') '; } @@ -300,7 +294,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc if (is_array($langRecUids[$langRow['uid']])) { $editUrl = BackendUtility::getModuleUrl('record_edit', [ 'edit' => [ - 'pages_language_overlay' => [ + 'pages' => [ implode(',', $langRecUids[$langRow['uid']]) => 'edit' ] ], @@ -315,7 +309,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc $editButton = ''; } // Create new overlay records: - $params = '&columnsOnly=title,hidden,sys_language_uid&overrideVals[pages_language_overlay][sys_language_uid]=' . $langRow['uid']; + $params = '&columnsOnly=title,hidden,sys_language_uid&overrideVals[pages][sys_language_uid]=' . $langRow['uid']; $onClick = BackendUtility::editOnClick($params); if (!empty($newOL_js[$langRow['uid']])) { $onClickArray = explode('?', $onClick, 2); @@ -387,12 +381,12 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc * * @param int $pageId Page ID to look up for. * @param int $langId Language UID to select for. - * @return array pages_languages_overlay record + * @return array translated pages record */ public function getLangStatus($pageId, $langId) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable(static::$pageLanguageOverlayTable); + ->getQueryBuilderForTable('pages'); $queryBuilder ->getRestrictions() ->removeAll() @@ -400,10 +394,10 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); $result = $queryBuilder ->select('*') - ->from(static::$pageLanguageOverlayTable) + ->from('pages') ->where( $queryBuilder->expr()->eq( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT) ) ) @@ -416,7 +410,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc ->execute(); $row = $result->fetch(); - BackendUtility::workspaceOL(static::$pageLanguageOverlayTable, $row); + BackendUtility::workspaceOL('pages', $row); if (is_array($row)) { $row['_COUNT'] = $result->rowCount(); $row['_HIDDEN'] = $row['hidden'] || (int)$row['endtime'] > 0 && (int)$row['endtime'] < $GLOBALS['EXEC_TIME'] || $GLOBALS['EXEC_TIME'] < (int)$row['starttime']; @@ -435,7 +429,7 @@ class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunc public function getContentElementCount($pageId, $sysLang) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable(static::$pageLanguageOverlayTable); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) diff --git a/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayBeGroupsAccessRights.php b/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayBeGroupsAccessRights.php new file mode 100644 index 0000000000000000000000000000000000000000..ba2587e8df1ca4237fc4d449b79f4ac3a48c56a0 --- /dev/null +++ b/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayBeGroupsAccessRights.php @@ -0,0 +1,124 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Install\Updates; + +/* + * 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\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * Merge access rights from be_groups concerning pages_language_overlay + * into pages + */ +class MigratePagesLanguageOverlayBeGroupsAccessRights extends AbstractUpdate +{ + /** + * The human-readable title of the upgrade wizard + * + * @var string + */ + protected $title = 'Merge be_groups access rights from pages_language_overlay to pages'; + + /** + * Checks whether updates are required. + * + * @param string &$description The description for the update + * @return bool Whether an update is required (TRUE) or not (FALSE) + */ + public function checkForUpdate(&$description) + { + $description = 'The table pages_language_overlay will be removed to align the translation ' . + 'handling for pages with the rest of the core. This wizard transfers all be_groups with ' . + 'access restrictions to pages_language_overlay into pages.'; + + $updateNeeded = false; + + if (!$this->isWizardDone()) { + $updateNeeded = true; + } + + return $updateNeeded; + } + + /** + * Performs the accordant updates. + * + * @param array &$dbQueries Queries done in this update + * @param string &$customMessage Custom message + * @return bool Whether everything went smoothly or not + * @throws \InvalidArgumentException + */ + public function performUpdate(array &$dbQueries, &$customMessage) + { + $beGroupsQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_groups'); + $beGroupsQueryBuilder->getRestrictions()->removeAll(); + $beGroupsRows = $beGroupsQueryBuilder + ->select('uid', 'non_exclude_fields', 'tables_modify') + ->from('be_groups') + ->execute(); + while ($beGroupsRow = $beGroupsRows->fetch()) { + $updateNeeded = false; + if (!empty($beGroupsRow['tables_modify'])) { + // If 'pages_language_overlay' is allowed as table-modify, remove it and add + // 'pages' if it is not in there, yet. + $tablesArray = GeneralUtility::trimExplode(',', $beGroupsRow['tables_modify'], true); + $newTablesArray = $tablesArray; + if (in_array('pages_language_overlay', $tablesArray, true)) { + $updateNeeded = true; + $newTablesArray = array_diff($tablesArray, ['pages_language_overlay']); + if (!in_array('pages', $newTablesArray, true)) { + $newTablesArray[] = 'pages'; + } + } + } else { + $newTablesArray = []; + } + if (!empty($beGroupsRow['non_exclude_fields'])) { + // Exclude fields on 'pages_language_overlay' are removed and added as + // exclude fields on 'pages' + $excludeFields = GeneralUtility::trimExplode(',', $beGroupsRow['non_exclude_fields'], true); + $newExcludeFields = []; + foreach ($excludeFields as $tableFieldCombo) { + if (strpos($tableFieldCombo, 'pages_language_overlay:') === 0) { + $updateNeeded = true; + $field = substr($tableFieldCombo, strlen('pages_language_overlay:')); + $newExcludeFields[] = 'pages:' . $field; + } else { + $newExcludeFields[] = $tableFieldCombo; + } + } + array_unique($newExcludeFields); + } else { + $newExcludeFields = []; + } + if ($updateNeeded) { + $updateBeGroupsQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_groups'); + $updateBeGroupsQueryBuilder + ->update('be_groups') + ->set('tables_modify', implode(',', $newTablesArray)) + ->set('non_exclude_fields', implode(',', $newExcludeFields)) + ->where( + $updateBeGroupsQueryBuilder->expr()->eq( + 'uid', + $updateBeGroupsQueryBuilder->createNamedParameter($beGroupsRow['uid'], \PDO::PARAM_INT) + ) + ) + ->execute(); + } + } + $this->markWizardAsDone(); + return true; + } +} diff --git a/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayUpdate.php b/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayUpdate.php new file mode 100644 index 0000000000000000000000000000000000000000..d208c557d1ca403b2241599b57384c746e4d324e --- /dev/null +++ b/typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayUpdate.php @@ -0,0 +1,296 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Install\Updates; + +/* + * 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\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Install\Service\LoadTcaService; + +/** + * Class MigratePagesLanguageOverlayUpdate + */ +class MigratePagesLanguageOverlayUpdate extends AbstractUpdate +{ + /** + * The human-readable title of the upgrade wizard + * + * @var string + */ + protected $title = 'Migrate content from pages_language_overlay to pages'; + + /** + * Checks whether updates are required. + * + * @param string &$description The description for the update + * @return bool Whether an update is required (TRUE) or not (FALSE) + */ + public function checkForUpdate(&$description) + { + $description = 'The table pages_language_overlay will be removed to align the translation ' . + 'handling for pages with the rest of the core. This wizard transfers all data to the pages ' . + 'table by creating new entries and linking them to the l10n parent. This might take a while, ' . + 'because max. (amount of pages) x (active languages) new entries need be created.'; + + $updateNeeded = false; + + if (!$this->isWizardDone()) { + $updateNeeded = true; + } + + return $updateNeeded; + } + + /** + * Shows information on the next step of the page + * + * @param string $formFieldNamePrefix + * @return string + */ + public function getUserInput($formFieldNamePrefix) + { + $message = ''; + // Warn for TCA relation configurations which are not migrated. + if (isset($GLOBALS['TCA']['pages_language_overlay']['columns']) && is_array($GLOBALS['TCA']['pages_language_overlay']['columns'])) { + foreach ($GLOBALS['TCA']['pages_language_overlay']['columns'] as $fieldName => $fieldConfiguration) { + if (isset($fieldConfiguration['config']['MM'])) { + $message .= '<p>The pages_language_overlay field ' . $fieldName + . ' with its MM relation configuration can not be migrated' + . ' automatically. Existing data relations to this field have' + . ' to be migrated manually.</p>'; + } + } + } + return $message; + } + + /** + * Performs the accordant updates. + * + * @param array &$dbQueries Queries done in this update + * @param string &$customMessage Custom message + * @return bool Whether everything went smoothly or not + * @throws \InvalidArgumentException + */ + public function performUpdate(array &$dbQueries, &$customMessage) + { + // Ensure pages_language_overlay is still available in TCA + GeneralUtility::makeInstance(LoadTcaService::class)->loadExtensionTablesWithoutMigration(); + $this->mergePagesLanguageOverlayIntoPages(); + $this->updateInlineRelations(); + $this->updateSysHistoryRelations(); + $this->markWizardAsDone(); + return true; + } + + /** + * 1. Fetches ALL pages_language_overlay (= translations) records + * 2. Fetches the given page record (= original language) for each translation + * 3. Populates the values from the original language IF the field in the translation record is NOT SET (empty is fine) + * 4. Adds proper fields for the translations which is + * - l10n_parent = UID of the original-language-record + * - pid = PID of the original-language-record (please note: THIS IS DIFFERENT THAN IN pages_language_overlay) + * - l10n_source = UID of the original-language-record (only this is supported currently) + */ + protected function mergePagesLanguageOverlayIntoPages() + { + $overlayQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages_language_overlay'); + $overlayQueryBuilder->getRestrictions()->removeAll(); + $overlayRecords = $overlayQueryBuilder + ->select('*') + ->from('pages_language_overlay') + ->execute(); + $pagesConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages'); + $pagesColumns = $pagesConnection->getSchemaManager()->listTableDetails('pages')->getColumns(); + $pagesColumnTypes = []; + foreach ($pagesColumns as $pageColumn) { + $pagesColumnTypes[$pageColumn->getName()] = $pageColumn->getType()->getBindingType(); + } + while ($overlayRecord = $overlayRecords->fetch()) { + // Early continue if record has been migrated before + if ($this->isOverlayRecordMigratedAlready((int)$overlayRecord['uid'])) { + continue; + } + + $values = []; + $originalPageId = (int)$overlayRecord['pid']; + $page = $this->fetchDefaultLanguagePageRecord($originalPageId); + if (!empty($page)) { + foreach ($pagesColumns as $pageColumn) { + $name = $pageColumn->getName(); + if (isset($overlayRecord[$name])) { + $values[$name] = $overlayRecord[$name]; + } elseif (isset($page[$name])) { + $values[$name] = $page[$name]; + } + } + + $values['pid'] = $page['pid']; + $values['l10n_parent'] = $originalPageId; + $values['l10n_source'] = $originalPageId; + $values['legacy_overlay_uid'] = $overlayRecord['uid']; + unset($values['uid']); + $pagesConnection->insert( + 'pages', + $values, + $pagesColumnTypes + ); + } + } + } + + /** + * Inline relations with foreign_field, foreign_table, foreign_table_field on + * pages_language_overlay TCA get their existing relations updated to new + * uid and pages table. + */ + protected function updateInlineRelations() + { + if (isset($GLOBALS['TCA']['pages_language_overlay']['columns']) && is_array($GLOBALS['TCA']['pages_language_overlay']['columns'])) { + foreach ($GLOBALS['TCA']['pages_language_overlay']['columns'] as $fieldName => $fieldConfiguration) { + // Migrate any 1:n relations + if ($fieldConfiguration['config']['type'] === 'inline' + && !empty($fieldConfiguration['config']['foreign_field']) + && !empty($fieldConfiguration['config']['foreign_table']) + && !empty($fieldConfiguration['config']['foreign_table_field']) + ) { + $foreignTable = trim($fieldConfiguration['config']['foreign_table']); + $foreignField = trim($fieldConfiguration['config']['foreign_field']); + $foreignTableField = trim($fieldConfiguration['config']['foreign_table_field']); + $translatedPagesQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $translatedPagesQueryBuilder->getRestrictions()->removeAll(); + $translatedPagesRows = $translatedPagesQueryBuilder + ->select('uid', 'legacy_overlay_uid') + ->from('pages') + ->where( + $translatedPagesQueryBuilder->expr()->gt( + 'l10n_parent', + $translatedPagesQueryBuilder->createNamedParameter(0, \PDO::PARAM_INT) + ) + ) + ->execute(); + while ($translatedPageRow = $translatedPagesRows->fetch()) { + $foreignTableQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($foreignTable); + $foreignTableQueryBuilder->getRestrictions()->removeAll(); + $foreignTableQueryBuilder + ->update($foreignTable) + ->set($foreignField, $translatedPageRow['uid']) + ->set($foreignTableField, 'pages') + ->where( + $foreignTableQueryBuilder->expr()->eq( + $foreignField, + $foreignTableQueryBuilder->createNamedParameter($translatedPageRow['legacy_overlay_uid'], \PDO::PARAM_INT) + ), + $foreignTableQueryBuilder->expr()->eq( + $foreignTableField, + $foreignTableQueryBuilder->createNamedParameter('pages_language_overlay', \PDO::PARAM_STR) + ) + ) + ->execute(); + } + } + } + } + } + + /** + * Update recuid and tablename of sys_history table to pages and new uid + * for all pages_language_overlay rows + */ + protected function updateSysHistoryRelations() + { + $translatedPagesQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $translatedPagesQueryBuilder->getRestrictions()->removeAll(); + $translatedPagesRows = $translatedPagesQueryBuilder + ->select('uid', 'legacy_overlay_uid') + ->from('pages') + ->where( + $translatedPagesQueryBuilder->expr()->gt( + 'l10n_parent', + $translatedPagesQueryBuilder->createNamedParameter(0, \PDO::PARAM_INT) + ) + ) + ->execute(); + while ($translatedPageRow = $translatedPagesRows->fetch()) { + $historyTableQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_history'); + $historyTableQueryBuilder->getRestrictions()->removeAll(); + $historyTableQueryBuilder + ->update('sys_history') + ->set('tablename', 'pages') + ->set('recuid', $translatedPageRow['uid']) + ->where( + $historyTableQueryBuilder->expr()->eq( + 'recuid', + $historyTableQueryBuilder->createNamedParameter($translatedPageRow['legacy_overlay_uid'], \PDO::PARAM_INT) + ), + $historyTableQueryBuilder->expr()->eq( + 'tablename', + $historyTableQueryBuilder->createNamedParameter('pages_language_overlay', \PDO::PARAM_STR) + ) + ) + ->execute(); + } + } + + /** + * Fetches a certain page + * + * @param int $pageId + * @return array + * @throws \InvalidArgumentException + */ + protected function fetchDefaultLanguagePageRecord(int $pageId): array + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll(); + $page = $queryBuilder + ->select('*') + ->from('pages') + ->where( + $queryBuilder->expr()->eq( + 'uid', + $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT) + ) + ) + ->execute() + ->fetch(); + return $page ?: []; + } + + /** + * Verify if a single overlay record has been migrated to pages already + * by checking the db field legacy_overlay_uid for the orig uid + * + * @param int $overlayUid + * @return bool + */ + protected function isOverlayRecordMigratedAlready(int $overlayUid): bool + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll(); + $migratedRecord = $queryBuilder + ->select('uid') + ->from('pages') + ->where( + $queryBuilder->expr()->eq( + 'legacy_overlay_uid', + $queryBuilder->createNamedParameter($overlayUid, \PDO::PARAM_INT) + ) + ) + ->execute() + ->fetch(); + return !empty($migratedRecord); + } +} diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index e720b6cb43a85298b5c6cd12be856ba23d80e07e..1780c888f3a8f4314e7a70dd3c4ce49471036cdb 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -1381,4 +1381,25 @@ return [ 'Deprecation-82926-DomainRelatedApiMethodInTSFE.rst', ], ], + 'TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->getTranslationTable' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-82445-PageTranslationRelatedFunctionality.rst', + ], + ], + 'TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->isTranslationInOwnTable' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-82445-PageTranslationRelatedFunctionality.rst', + ], + ], + 'TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider->foreignTranslationTable' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-82445-PageTranslationRelatedFunctionality.rst', + ], + ], ]; diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php index ac5210ae926f799cd2dd621c3081e85384c7da30..3edd1528ac48d72e1a3973a5eca6cee27ee5c43d 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php @@ -498,4 +498,11 @@ return [ 'Deprecation-82902-CustomBackendModuleRegistrationMethods.rst', ], ], + 'TYPO3\CMS\Backend\Utility\BackendUtility::getOriginalTranslationTable' => [ + 'numberOfMandatoryArguments' => 1, + 'maximumNumberOfArguments' => 1, + 'restFiles' => [ + 'Deprecation-82445-PageTranslationRelatedFunctionality.rst', + ], + ], ]; diff --git a/typo3/sysext/install/ext_localconf.php b/typo3/sysext/install/ext_localconf.php index c0843db3145eda71be64d0602980b2337cd685f8..765af304583255927e1e3ac613db40362976057d 100644 --- a/typo3/sysext/install/ext_localconf.php +++ b/typo3/sysext/install/ext_localconf.php @@ -50,6 +50,10 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['rdctExtensio = \TYPO3\CMS\Install\Updates\RedirectExtractionUpdate::class; $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['cshmanualBackendUsers'] = \TYPO3\CMS\Install\Updates\BackendUserStartModuleUpdate::class; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['pagesLanguageOverlay'] + = \TYPO3\CMS\Install\Updates\MigratePagesLanguageOverlayUpdate::class; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['pagesLanguageOverlayBeGroupsAccessRights'] + = \TYPO3\CMS\Install\Updates\MigratePagesLanguageOverlayBeGroupsAccessRights::class; $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class); $icons = [ diff --git a/typo3/sysext/recordlist/Classes/RecordList.php b/typo3/sysext/recordlist/Classes/RecordList.php index f9f4b1f72abec2dc9b7dea68f8aca5a30b54cae9..85b77ff316cde6ad865737bd544ff5fa2a6ed947 100644 --- a/typo3/sysext/recordlist/Classes/RecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList.php @@ -22,6 +22,8 @@ use TYPO3\CMS\Backend\Template\DocumentTemplate; use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Database\ConnectionPool; +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; @@ -32,6 +34,7 @@ use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\TypoScript\TypoScriptService; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Versioning\VersionState; /** * Script Class for the Web > List module; rendering the listing of records on a page @@ -465,10 +468,16 @@ class RecordList $this->body = $this->moduleTemplate->header($title); $this->moduleTemplate->setTitle($title); + $output = ''; + // Show the selector for new translations of the current page + // but only when in "default" mode + if ($this->id && !$dblist->csvOutput && !$this->search_field && !$this->cmd && !$this->table) { + $output .= $this->languageSelector($this->id); + } + if (!empty($dblist->HTMLcode)) { - $output = $dblist->HTMLcode; + $output .= $dblist->HTMLcode; } else { - $output = ''; $flashMessage = GeneralUtility::makeInstance( FlashMessage::class, $lang->getLL('noRecordsOnThisPage'), @@ -596,6 +605,146 @@ class RecordList return $response; } + /** + * Make selector box for creating new translation in a language + * Displays only languages which are not yet present for the current page and + * that are not disabled with page TS. + * + * @param int $id Page id for which to create a new translation record of pages + * @return string <select> HTML element (if there were items for the box anyways...) + */ + protected function languageSelector(int $id): string + { + if ($this->getBackendUserAuthentication()->check('tables_modify', 'pages')) { + // First, select all + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(HiddenRestriction::class)); + $statement = $queryBuilder->select('uid', 'title') + ->from('sys_language') + ->orderBy('sorting') + ->execute(); + $availableTranslations = []; + while ($row = $statement->fetch()) { + if ($this->getBackendUserAuthentication()->checkLanguageAccess($row['uid'])) { + $availableTranslations[(int)$row['uid']] = $row['title']; + } + } + // Then, subtract the languages which are already on the page: + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language'); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder->select('sys_language.uid AS uid', 'sys_language.title AS title') + ->from('sys_language') + ->join( + 'sys_language', + 'pages', + 'pages', + $queryBuilder->expr()->eq('sys_language.uid', $queryBuilder->quoteIdentifier('pages.sys_language_uid')) + ) + ->where( + $queryBuilder->expr()->eq( + 'pages.deleted', + $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) + ), + $queryBuilder->expr()->eq( + 'pages.l10n_parent', + $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT) + ), + $queryBuilder->expr()->orX( + $queryBuilder->expr()->gte( + 'pages.t3ver_state', + $queryBuilder->createNamedParameter( + (string)new VersionState(VersionState::DEFAULT_STATE), + \PDO::PARAM_INT + ) + ), + $queryBuilder->expr()->eq( + 'pages.t3ver_wsid', + $queryBuilder->createNamedParameter($this->getBackendUserAuthentication()->workspace, \PDO::PARAM_INT) + ) + ) + ) + ->groupBy( + 'pages.sys_language_uid', + 'sys_language.uid', + 'sys_language.pid', + 'sys_language.tstamp', + 'sys_language.hidden', + 'sys_language.title', + 'sys_language.language_isocode', + 'sys_language.static_lang_isocode', + 'sys_language.flag', + 'sys_language.sorting' + ) + ->orderBy('sys_language.sorting'); + if (!$this->getBackendUserAuthentication()->isAdmin()) { + $queryBuilder->andWhere( + $queryBuilder->expr()->eq( + 'sys_language.hidden', + $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) + ) + ); + } + $statement = $queryBuilder->execute(); + while ($row = $statement->fetch()) { + unset($availableTranslations[(int)$row['uid']]); + } + // Remove disallowed languages + if (!empty($availableTranslations) + && !$this->getBackendUserAuthentication()->isAdmin() + && $this->getBackendUserAuthentication()->groupData['allowed_languages'] !== '' + ) { + $allowed_languages = array_flip(explode(',', $this->getBackendUserAuthentication()->groupData['allowed_languages'])); + if (!empty($allowed_languages)) { + foreach ($availableTranslations as $key => $value) { + if (!isset($allowed_languages[$key]) && $key != 0) { + unset($availableTranslations[$key]); + } + } + } + } + // Remove disabled languages + $modSharedTSconfig = BackendUtility::getModTSconfig($id, 'mod.SHARED'); + $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages']) + ? GeneralUtility::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], true) + : []; + if (!empty($availableTranslations) && !empty($disableLanguages)) { + foreach ($disableLanguages as $language) { + if ($language != 0 && isset($availableTranslations[$language])) { + unset($availableTranslations[$language]); + } + } + } + // If any languages are left, make selector: + if (!empty($availableTranslations)) { + $output = '<option value="">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:new_language')) . '</option>'; + foreach ($availableTranslations as $languageUid => $languageTitle) { + // Build localize command URL to DataHandler (tce_db) + // which redirects to FormEngine (record_edit) + // which, when finished editing should return back to the current page (returnUrl) + $parameters = [ + 'justLocalized' => 'pages:' . $id . ':' . $languageUid, + 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') + ]; + $redirectUrl = BackendUtility::getModuleUrl('record_edit', $parameters); + $targetUrl = BackendUtility::getLinkToDataHandlerAction( + '&cmd[pages][' . $id . '][localize]=' . $languageUid, + $redirectUrl + ); + + $output .= '<option value="' . htmlspecialchars($targetUrl) . '">' . htmlspecialchars($languageTitle) . '</option>'; + } + + return '<div class="form-inline form-inline-spaced">' + . '<div class="form-group">' + . '<select class="form-control input-sm" name="createNewLanguage" onchange="window.location.href=this.options[this.selectedIndex].value">' + . $output + . '</select></div></div>'; + } + } + return ''; + } + /** * @return ModuleTemplate */ diff --git a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php index e3c79fec27d03419efadc2cd5f4475b96605d861..7d249d093625a04677f6483de657da2eb8bdec6b 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/AbstractDatabaseRecordList.php @@ -804,9 +804,7 @@ class AbstractDatabaseRecordList extends AbstractRecordList } // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set - if ( - $table !== 'pages_language_overlay' - && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) + if (!empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && (GeneralUtility::inList($this->hideTranslations, $table) || $this->hideTranslations === '*') ) { $queryBuilder->andWhere($queryBuilder->expr()->eq( diff --git a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php index 9465d4c29017c45f18dabb35b24a1562934d41ea..f77fa8c2db2d2858c845f93173a4bce81f4f5c40 100644 --- a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php +++ b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php @@ -917,8 +917,7 @@ class DatabaseRecordList $titleCol = $GLOBALS['TCA'][$table]['ctrl']['label']; $thumbsCol = $GLOBALS['TCA'][$table]['ctrl']['thumbnail']; $l10nEnabled = $GLOBALS['TCA'][$table]['ctrl']['languageField'] - && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] - && $table !== 'pages_language_overlay'; + && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; $tableCollapsed = (bool)$this->tablesCollapsed[$table]; // prepare space icon $this->spaceIcon = '<span class="btn btn-default disabled">' . $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render() . '</span>'; @@ -1435,7 +1434,6 @@ class DatabaseRecordList $theData['uid'] = $row['uid']; if (isset($GLOBALS['TCA'][$table]['ctrl']['languageField']) && isset($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) - && $table !== 'pages_language_overlay' ) { $theData['_l10nparent_'] = $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']]; } @@ -1619,8 +1617,8 @@ class DatabaseRecordList . $spriteIcon->render() . '</a>'; } else { $params = '&edit[' . $table . '][' . $this->id . ']=new'; - if ($table === 'pages_language_overlay') { - $params .= '&overrideVals[pages_language_overlay][doktype]=' . (int)$this->pageRow['doktype']; + if ($table === 'pages') { + $params .= '&overrideVals[pages][doktype]=' . (int)$this->pageRow['doktype']; } $icon = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick($params, '', -1)) . '" title="' . htmlspecialchars($lang->getLL('new')) . '">' . $spriteIcon->render() . '</a>'; @@ -1850,6 +1848,9 @@ class DatabaseRecordList 'primary' => [], 'secondary' => [] ]; + // Enables to hide the move elements for localized records - doesn't make much sense to perform these options for them + // For page translations these icons should never be shown + $isL10nOverlay = ($this->localizationView || $table === 'pages') && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0; // If the listed table is 'pages' we have to request the permission settings for each page: $localCalcPerms = 0; if ($table === 'pages') { @@ -1902,10 +1903,14 @@ class DatabaseRecordList $this->addActionToCellGroup($cells, $viewBigAction, 'viewBig'); // "Move" wizard link for pages/tt_content elements: if ($permsEdit && ($table === 'tt_content' || $table === 'pages')) { - $onClick = 'return jumpExt(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('move_element') . '&table=' . $table . '&uid=' . $row['uid']) . ');'; - $linkTitleLL = htmlspecialchars($this->getLanguageService()->getLL('move_' . ($table === 'tt_content' ? 'record' : 'page'))); - $icon = ($table === 'pages' ? $this->iconFactory->getIcon('actions-page-move', Icon::SIZE_SMALL) : $this->iconFactory->getIcon('actions-document-move', Icon::SIZE_SMALL)); - $moveAction = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $linkTitleLL . '">' . $icon->render() . '</a>'; + if ($isL10nOverlay) { + $moveAction = $this->spaceIcon; + } else { + $onClick = 'return jumpExt(' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('move_element') . '&table=' . $table . '&uid=' . $row['uid']) . ');'; + $linkTitleLL = htmlspecialchars($this->getLanguageService()->getLL('move_' . ($table === 'tt_content' ? 'record' : 'page'))); + $icon = ($table === 'pages' ? $this->iconFactory->getIcon('actions-page-move', Icon::SIZE_SMALL) : $this->iconFactory->getIcon('actions-document-move', Icon::SIZE_SMALL)); + $moveAction = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $linkTitleLL . '">' . $icon->render() . '</a>'; + } $this->addActionToCellGroup($cells, $moveAction, 'move'); } // If the table is NOT a read-only table, then show these links: @@ -1919,17 +1924,23 @@ class DatabaseRecordList $this->addActionToCellGroup($cells, $historyAction, 'history'); // "Edit Perms" link: if ($table === 'pages' && $this->getBackendUserAuthentication()->check('modules', 'system_BeuserTxPermission') && ExtensionManagementUtility::isLoaded('beuser')) { - $href = BackendUtility::getModuleUrl('system_BeuserTxPermission') . '&id=' . $row['uid'] . '&tx_beuser_system_beusertxpermission[action]=edit' . $this->makeReturnUrl(); - $permsAction = '<a class="btn btn-default" href="' . htmlspecialchars($href) . '" title="' - . htmlspecialchars($this->getLanguageService()->getLL('permissions')) . '">' - . $this->iconFactory->getIcon('actions-lock', Icon::SIZE_SMALL)->render() . '</a>'; + if ($isL10nOverlay) { + $permsAction = $this->spaceIcon; + } else { + $href = BackendUtility::getModuleUrl('system_BeuserTxPermission') . '&id=' . $row['uid'] . '&tx_beuser_system_beusertxpermission[action]=edit' . $this->makeReturnUrl(); + $permsAction = '<a class="btn btn-default" href="' . htmlspecialchars($href) . '" title="' + . htmlspecialchars($this->getLanguageService()->getLL('permissions')) . '">' + . $this->iconFactory->getIcon('actions-lock', Icon::SIZE_SMALL)->render() . '</a>'; + } $this->addActionToCellGroup($cells, $permsAction, 'perms'); } // "New record after" link (ONLY if the records in the table are sorted by a "sortby"-row // or if default values can depend on previous record): if (($GLOBALS['TCA'][$table]['ctrl']['sortby'] || $GLOBALS['TCA'][$table]['ctrl']['useColumnsForDefaultValues']) && $permsEdit) { if ($table !== 'pages' && $this->calcPerms & Permission::CONTENT_EDIT || $table === 'pages' && $this->calcPerms & Permission::PAGE_NEW) { - if ($this->showNewRecLink($table)) { + if ($table === 'pages' && $isL10nOverlay) { + $this->addActionToCellGroup($cells, $this->spaceIcon, 'new'); + } elseif ($this->showNewRecLink($table)) { $params = '&edit[' . $table . '][' . -($row['_MOVE_PLH'] ? $row['_MOVE_PLH_uid'] : $row['uid']) . ']=new'; $icon = ($table === 'pages' ? $this->iconFactory->getIcon('actions-page-new', Icon::SIZE_SMALL) : $this->iconFactory->getIcon('actions-add', Icon::SIZE_SMALL)); $titleLabel = 'new'; @@ -1945,7 +1956,7 @@ class DatabaseRecordList } // "Up/Down" links if ($permsEdit && $GLOBALS['TCA'][$table]['ctrl']['sortby'] && !$this->sortField && !$this->searchLevels) { - if (isset($this->currentTable['prev'][$row['uid']])) { + if (!$isL10nOverlay && isset($this->currentTable['prev'][$row['uid']])) { // Up $params = '&cmd[' . $table . '][' . $row['uid'] . '][move]=' . $this->currentTable['prev'][$row['uid']]; $moveUpAction = '<a class="btn btn-default" href="#" onclick="' @@ -1957,7 +1968,7 @@ class DatabaseRecordList } $this->addActionToCellGroup($cells, $moveUpAction, 'moveUp'); - if ($this->currentTable['next'][$row['uid']]) { + if (!$isL10nOverlay && $this->currentTable['next'][$row['uid']]) { // Down $params = '&cmd[' . $table . '][' . $row['uid'] . '][move]=' . $this->currentTable['next'][$row['uid']]; $moveDownAction = '<a class="btn btn-default" href="#" onclick="' @@ -2050,10 +2061,10 @@ class DatabaseRecordList . htmlspecialchars('return jumpToUrl(' . BackendUtility::getLinkToDataHandlerAction($params, -1) . ');') . '" title="' . htmlspecialchars($this->getLanguageService()->getLL('prevLevel')) . '">' . $this->iconFactory->getIcon('actions-move-left', Icon::SIZE_SMALL)->render() . '</a>'; - $this->addActionToCellGroup($cells, $moveLeftAction, 'moveLeft'); + $this->addActionToCellGroup($cells, $isL10nOverlay ? $this->spaceIcon : $moveLeftAction, 'moveLeft'); } // Down (Paste as subpage to the page right above) - if ($this->currentTable['prevUid'][$row['uid']]) { + if (!$isL10nOverlay && $this->currentTable['prevUid'][$row['uid']]) { $localCalcPerms = $this->getBackendUserAuthentication()->calcPerms(BackendUtility::getRecord('pages', $this->currentTable['prevUid'][$row['uid']])); if ($localCalcPerms & Permission::PAGE_NEW) { $params = '&cmd[' . $table . '][' . $row['uid'] . '][move]=' . $this->currentTable['prevUid'][$row['uid']]; @@ -2148,8 +2159,9 @@ class DatabaseRecordList } $cells = []; $cells['pasteAfter'] = ($cells['pasteInto'] = $this->spaceIcon); - //enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them - $isL10nOverlay = $this->localizationView && $table !== 'pages_language_overlay' && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0; + // Enables to hide the copy, cut and paste icons for localized records - doesn't make much sense to perform these options for them + // For page translations these icons should never be shown + $isL10nOverlay = ($this->localizationView || $table === 'pages') && $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0; // Return blank, if disabled: // Whether a numeric clipboard pad is active or the normal pad we will see different content of the panel: // For the "Normal" pad: @@ -2194,7 +2206,7 @@ class DatabaseRecordList $cells['cut'] = $this->spaceIcon; } } else { - if ($table !== 'pages' && $this->calcPerms & Permission::CONTENT_EDIT) { + if ($this->calcPerms & Permission::CONTENT_EDIT) { $cells['cut'] = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars('return jumpSelf(' . GeneralUtility::quoteJSvalue($this->clipObj->selUrlDB($table, $row['uid'], 0, ($isSel === 'cut'), ['returnUrl' => ''])) . ');') . '" title="' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:cm.cut')) . '">' @@ -2241,7 +2253,7 @@ class DatabaseRecordList } // Now, looking for elements in general: $elFromTable = $this->clipObj->elFromTable(''); - if ($table === 'pages' && !empty($elFromTable)) { + if ($table === 'pages' && !$isL10nOverlay && !empty($elFromTable)) { $cells['pasteInto'] = '<a class="btn btn-default t3js-modal-trigger"' . ' href="' . htmlspecialchars($this->clipObj->pasteUrl('', $row['uid'])) . '"' . ' title="' . htmlspecialchars($this->getLanguageService()->getLL('clip_pasteInto')) . '"' @@ -2266,9 +2278,7 @@ class DatabaseRecordList $cells = $hookObject->makeClip($table, $row, $cells, $this); } } - // Compile items into a DIV-element: - return '<!-- CLIPBOARD PANEL: ' . $table . ':' . $row['uid'] . ' --> - <div class="btn-group" role="group">' . implode('', $cells) . '</div>'; + return '<div class="btn-group" role="group">' . implode('', $cells) . '</div>'; } /** @@ -3181,9 +3191,7 @@ class DatabaseRecordList } // Filter out records that are translated, if TSconfig mod.web_list.hideTranslations is set - if ( - $table !== 'pages_language_overlay' - && !empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) + if (!empty($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) && (GeneralUtility::inList($this->hideTranslations, $table) || $this->hideTranslations === '*') ) { $queryBuilder->andWhere( @@ -4088,17 +4096,17 @@ class DatabaseRecordList { // Look up page overlays: $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder ->select('*') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->andX( - $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), + $queryBuilder->expr()->eq('l10n_parent', $queryBuilder->createNamedParameter($this->id, \PDO::PARAM_INT)), $queryBuilder->expr()->gt( 'sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT) diff --git a/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php b/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php index de87dd2f468c29d483633a7d4fe2dba6e7e9db28..f3fcd4710cc3dae44247dac8c6d018ac6d3dae76 100644 --- a/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php +++ b/typo3/sysext/viewpage/Classes/Controller/ViewModuleController.php @@ -329,13 +329,13 @@ class ViewModuleController extends ActionController ->from('sys_language') ->join( 'sys_language', - 'pages_language_overlay', + 'pages', 'o', $queryBuilder->expr()->eq('o.sys_language_uid', $queryBuilder->quoteIdentifier('sys_language.uid')) ) ->where( $queryBuilder->expr()->eq( - 'o.pid', + 'o.l10n_parent', $queryBuilder->createNamedParameter($pageIdToShow, \PDO::PARAM_INT) ) ) diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php index 2819d812f43705483cfbfb801f9cbcdc0da58770..4e751a8eccc48bf6b7939cef4c862308429662cd 100644 --- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php +++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php @@ -838,7 +838,7 @@ class DataHandlerHook } // l10n-fields must be kept otherwise the localization // will be lost during the publishing - if ($table !== 'pages_language_overlay' && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) { + if ($GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']) { $keepFields[] = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; } // Swap "keepfields" diff --git a/typo3/sysext/workspaces/Classes/Service/StagesService.php b/typo3/sysext/workspaces/Classes/Service/StagesService.php index 4d41cf87c8d1c4fc95b3b9da553af7a89673eeff..6d7855d300f852b7f1dff10e9b34f81b25642bde 100644 --- a/typo3/sysext/workspaces/Classes/Service/StagesService.php +++ b/typo3/sysext/workspaces/Classes/Service/StagesService.php @@ -90,7 +90,7 @@ class StagesService implements \TYPO3\CMS\Core\SingletonInterface */ public function getPreviousStageForElementCollection( $workspaceItems, - array $byTableName = ['tt_content', 'pages', 'pages_language_overlay'] + array $byTableName = ['tt_content', 'pages'] ) { $currentStage = []; $previousStage = []; @@ -138,7 +138,7 @@ class StagesService implements \TYPO3\CMS\Core\SingletonInterface */ public function getNextStageForElementCollection( $workspaceItems, - array $byTableName = ['tt_content', 'pages', 'pages_language_overlay'] + array $byTableName = ['tt_content', 'pages'] ) { $currentStage = []; $usedStages = []; diff --git a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php index 414e0acbbc9c99795655abce112d9eba052e1c1b..4824a5fcbb85dd36830c9d34ca4b266c1e955a76 100644 --- a/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php +++ b/typo3/sysext/workspaces/Classes/Service/WorkspaceService.php @@ -693,19 +693,19 @@ class WorkspaceService implements SingletonInterface // If the language is not default, check state of overlay if ($language > 0) { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)); $row = $queryBuilder->select('t3ver_state') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->eq( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages_language_overlay']['ctrl']['languageField'], + $GLOBALS['TCA']['pages']['ctrl']['languageField'], $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT) ), $queryBuilder->expr()->eq( @@ -769,7 +769,7 @@ class WorkspaceService implements SingletonInterface $viewUrl = ''; // Directly use determined direct page id - if ($table === 'pages_language_overlay' || $table === 'tt_content') { + if ($table === 'tt_content') { $viewUrl = BackendUtility::viewOnClick($previewPageId, '', null, '', '', $additionalParameters); } elseif (!empty($pageTsConfig['options.']['workspaces.']['previewPageId.'][$table]) || !empty($pageTsConfig['options.']['workspaces.']['previewPageId'])) { // Analyze Page TSconfig options.workspaces.previewPageId @@ -1137,17 +1137,17 @@ class WorkspaceService implements SingletonInterface } $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages_language_overlay'); + ->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class)); $result = $queryBuilder->select('sys_language_uid') - ->from('pages_language_overlay') + ->from('pages') ->where( $queryBuilder->expr()->eq( - 'pid', + 'l10n_parent', $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT) ) ) diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv index 611e170ec6ed76e72d52b0b55df213b09836c1e7..0bff9873fe3742c4f7de835e3d6a7b4012adb2dc 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/localizePage.csv @@ -1,13 +1,11 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,Relations -,90,88,512,0,0,0,0,0,0,0,Target -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,1,1,0,0,"[Translate to Dansk:] Relations" -,2,-1,0,1,1,-1,0,1,"[Translate to Dansk:] Relations" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,Relations +,90,88,512,0,0,0,0,0,0,0,0,0,Target +,91,88,256,0,1,89,0,1,1,0,0,0,"[Translate to Dansk:] Relations" +,92,-1,256,0,1,89,0,1,-1,0,91,0,"[Translate to Dansk:] Relations" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php index b90b41eda1471bfe4d8aade946b628d09e8f42e2..103c7216de4b7375abf9c071c69f3f8b7de03355 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php @@ -379,7 +379,7 @@ class ActionTest extends \TYPO3\CMS\Workspaces\Tests\Functional\DataHandling\Reg public function localizePage() { parent::localizePage(); - $this->actionService->publishRecord(self::TABLE_PageOverlay, $this->recordIds['localizedPageOverlayId']); + $this->actionService->publishRecord(self::TABLE_Page, $this->recordIds['localizedPageId']); $this->assertAssertionDataSet('localizePage'); $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections(); diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/localizePage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/localizePage.csv index 8c923a881837baee6a6fe74a638712bdc2f0093d..31fe6bfc4cac9c50c1b03f784425e2e30255de7e 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/localizePage.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/localizePage.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,Relations -,90,88,512,0,0,0,0,0,0,0,Target -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,Relations +,90,88,512,0,0,0,0,0,0,0,0,0,Target +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/localizePage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/localizePage.csv index 8c923a881837baee6a6fe74a638712bdc2f0093d..31fe6bfc4cac9c50c1b03f784425e2e30255de7e 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/localizePage.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/localizePage.csv @@ -1,12 +1,10 @@ pages -,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title -,1,0,256,0,0,0,0,0,0,0,FunctionalTest -,88,1,256,0,0,0,0,0,0,0,DataHandlerTest -,89,88,256,0,0,0,0,0,0,0,Relations -,90,88,512,0,0,0,0,0,0,0,Target -pages_language_overlay -,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title -,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations" +,uid,pid,sorting,deleted,sys_language_uid,l10n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title +,1,0,256,0,0,0,0,0,0,0,0,0,FunctionalTest +,88,1,256,0,0,0,0,0,0,0,0,0,DataHandlerTest +,89,88,256,0,0,0,0,0,0,0,0,0,Relations +,90,88,512,0,0,0,0,0,0,0,0,0,Target +,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations" tt_content ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,l10n_source,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header ,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0" diff --git a/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php b/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php index c8ecf179ec0d2b17589ab06aa0818a275c7c9c89..93d5b6b50dad8aa17f98ed57266ceca3b8b72562 100644 --- a/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php +++ b/typo3/sysext/workspaces/Tests/Functional/Service/WorkspaceServiceTest.php @@ -239,7 +239,6 @@ class WorkspaceServiceTest extends FunctionalTestCase 'sys_file_metadata' => [], 'sys_file_reference' => [], 'backend_layout' => [], - 'pages_language_overlay' => [], 'sys_template' => [], 'tt_content' => [ 1 => true,