Commit 234d24b8 authored by Simon Gilli's avatar Simon Gilli Committed by Andreas Fernandez
Browse files

[BUGFIX] Show content for columns with colPos set only

Setting up backend layouts with colPos not set will show the content of
column 0 because of an excplicit cast of the colPos. This patch checks
if colPos is set and if not skips the assignment of records.

Resolves: #91176
Releases: master, 10.4
Change-Id: I75d9818c4330bb8a4d9a7a60130a547167a83e58
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/64853


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 46e53dca
......@@ -114,11 +114,13 @@ class BackendLayoutRenderer
foreach ($row['columns.'] as $column) {
$columnObject = GeneralUtility::makeInstance(GridColumn::class, $context, $column);
$rowObject->addColumn($columnObject);
$records = $this->contentFetcher->getContentRecordsPerColumn((int)$column['colPos'], $languageId);
$recordRememberer->rememberRecords($records);
foreach ($records as $contentRecord) {
$columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $context, $columnObject, $contentRecord);
$columnObject->addItem($columnItem);
if (isset($column['colPos'])) {
$records = $this->contentFetcher->getContentRecordsPerColumn((int)$column['colPos'], $languageId);
$recordRememberer->rememberRecords($records);
foreach ($records as $contentRecord) {
$columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $context, $columnObject, $contentRecord);
$columnObject->addItem($columnItem);
}
}
}
$grid->addRow($rowObject);
......
<?php
declare(strict_types=1);
/*
* 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!
*/
namespace TYPO3\CMS\Backend\Tests\Functional\View\BackendLayout\Drawing;
use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout;
use TYPO3\CMS\Backend\View\Drawing\BackendLayoutRenderer;
use TYPO3\CMS\Backend\View\PageLayoutContext;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerFactory;
use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\Scenario\DataHandlerWriter;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
/**
* Testing rendering of backend layouts.
*/
class BackendLayoutRendererTest extends FunctionalTestCase
{
use SiteBasedTestTrait;
/**
* @var string[]
*/
protected $coreExtensionsToLoad = ['workspaces'];
/**
* @var BackendUserAuthentication
*/
private $backendUser;
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
static::initializeDatabaseSnapshot();
}
public static function tearDownAfterClass(): void
{
static::destroyDatabaseSnapshot();
parent::tearDownAfterClass();
}
protected function setUp(): void
{
parent::setUp();
$this->backendUser = $this->setUpBackendUserFromFixture(1);
$this->withDatabaseSnapshot(function () {
$this->setUpDatabase();
});
}
protected function tearDown(): void
{
unset($this->backendUser);
parent::tearDown();
}
protected function setUpDatabase()
{
Bootstrap::initializeLanguageObject();
$scenarioFile = __DIR__ . '/../Fixtures/DefaultViewScenario.yaml';
$factory = DataHandlerFactory::fromYamlFile($scenarioFile);
$writer = DataHandlerWriter::withBackendUser($this->backendUser);
$writer->invokeFactory($factory);
static::failIfArrayIsNotEmpty(
$writer->getErrors()
);
}
/**
* @param int $pageId
* @param array $configuration BackendLayout configuration
* @return PageLayoutContext|\PHPUnit\Framework\MockObject\MockObject
*/
protected function getPageLayoutContext(int $pageId, array $configuration)
{
// Create a BackendLayout
$backendLayout = new BackendLayout('layout1', 'Layout 1', $configuration);
// Create a mock for the PageLayoutContext class
return $this->createConfiguredMock(
PageLayoutContext::class,
[
'getBackendLayout' => $backendLayout,
'getPageId' => $pageId,
]
);
}
/**
* @param PageLayoutContext|\PHPUnit\Framework\MockObject\MockObject $context
* @return BackendLayoutRenderer
*/
protected function getSubject(PageLayoutContext $context)
{
return GeneralUtility::makeInstance(BackendLayoutRenderer::class, $context);
}
/**
* @test
*/
public function emptyBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(0, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
}
/**
* @test
*/
public function oneRowBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(0, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
}
/**
* @test
*/
public function multipleRowsBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [],
],
1 => [
'columns.' => [],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(2, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(0, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
}
/**
* @test
*/
public function oneRowOneColBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [
0 => [
'colPos' => 0
],
],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
foreach ($subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns() as $column) {
self::assertCount(1, $column->getItems());
}
}
/**
* @test
*/
public function oneRowMultipleColsBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [
0 => [
'colPos' => 0
],
1 => [
'colPos' => 1
],
],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(2, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
foreach ($subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns() as $column) {
self::assertCount(1, $column->getItems());
}
}
/**
* @test
*/
public function multipleRowsOneColBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [
0 => [
'colPos' => 0
],
],
],
1 => [
'columns.' => [
0 => [
'colPos' => 1
],
],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(2, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(2, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
foreach ($subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns() as $column) {
self::assertCount(1, $column->getItems());
}
}
/**
* @test
*/
public function multipleRowsMultipleColsBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [
0 => [
'colPos' => 0
],
1 => [
'colPos' => 1
],
],
],
1 => [
'columns.' => [
0 => [
'colPos' => 2
],
1 => [
'colPos' => 3
],
],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(2, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(4, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
foreach ($subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns() as $column) {
self::assertCount(1, $column->getItems());
}
}
/**
* @test
*/
public function noColPosBackendLayoutIsRendered()
{
$configuration['__config']['backend_layout.'] = [
'rows.' => [
0 => [
'columns.' => [
0 => [
],
1 => [
],
],
],
],
];
$pageLayoutContext = $this->getPageLayoutContext(1100, $configuration);
$subject = $this->getSubject($pageLayoutContext);
// Test the subject
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getRows());
self::assertCount(1, $subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns());
foreach ($subject->getGridForPageLayoutContext($pageLayoutContext)->getColumns() as $column) {
self::assertCount(0, $column->getItems());
}
}
}
__variables:
- &pageStandard 0
- &pageShortcut 4
- &pageMount 7
- &pageFolder 254
- &contentText 'text'
- &idAcmeRootPage 1000
- &idAcmeFirstPage 1100
entitySettings:
'*':
nodeColumnName: 'pid'
columnNames: {id: 'uid', language: 'sys_language_uid'}
defaultValues: {pid: 0}
page:
isNode: true
tableName: 'pages'
parentColumnName: 'pid'
languageColumnNames: ['l10n_parent', 'l10n_source']
columnNames: {type: 'doktype', root: 'is_siteroot', mount: 'mount_pid', visitorGroups: 'fe_group'}
defaultValues: {hidden: 0, doktype: *pageStandard}
valueInstructions:
shortcut:
first: {shortcut: 0, shortcut_mode: 1}
content:
tableName: 'tt_content'
languageColumnNames: ['l18n_parent', 'l10n_source']
columnNames: {title: 'header', type: 'CType', colPos: 'colPos'}
defaultValues: {colPos: 0}
workspace:
tableName: 'sys_workspace'
language:
tableName: 'sys_language'
columnNames: {code: 'language_isocode'}
visitorGroup:
tableName: 'fe_groups'
visitor:
tableName: 'fe_users'
columnNames: {groups: 'usergroup'}
typoscript:
tableName: 'sys_template'
valueInstructions:
type:
site: {root: 1, clear: 1}
entities:
workspace:
- self: {id: 1, title: 'Workspace'}
language:
- self: {id: 1, title: 'French', code: 'fr'}
- self: {id: 2, title: 'Franco-Canadian', code: 'fr'}
page:
- self: {id: *idAcmeRootPage, title: 'ACME Inc', type: *pageShortcut, shortcut: 'first', root: true}
children:
- self: {id: *idAcmeFirstPage, title: 'EN: Welcome'}
languageVariants:
- self: {id: 1101, title: 'FR: Welcome', language: 1}
- self: {id: 1102, title: 'FR-CA: Welcome', language: 2}
versionVariants:
- version: {title: 'EN: Welcome to ACME Inc', workspace: 1}
entities:
content:
- self: {title: 'EN: Content Element #1 colPos #0', type: *contentText, }
# @todo does not work due to a bug in DataHandler's remap stack for l10n_source
languageVariants:
- self: {title: 'FR: Content Element #1', type: *contentText, language: 1}
languageVariants:
- self: {title: 'FR-CA: Content Element #1', type: *contentText, language: 2}
- self: {title: 'EN: Content Element #2 colPos #1', type: *contentText, colPos: 1}
- self: {title: 'EN: Content Element #3 colPos #2', type: *contentText, colPos: 2}
- self: {title: 'EN: Content Element #4 colPos #3', type: *contentText, colPos: 3}
- self: {id: 1200, title: 'EN: Features'}
children:
- self: {id: 1210, title: 'EN: Frontend Editing'}
- self: {id: 1300, title: 'EN: Products'}
children:
- self: {id: 1310, title: 'EN: Planets'}
- self: {id: 1320, title: 'EN: Spaceships'}
- self: {id: 1330, title: 'EN: Dark Matter'}
- self: {id: 1400, title: 'EN: ACME in your Region'}
languageVariants:
- self: {id: 1401, title: 'FR: ACME in your Region', language: 1}
- self: {id: 1402, title: 'FR-CA: ACME in your Region', language: 2}
children:
- self: {id: 1410, title: 'EN: Groups', l18n_cfg: 1}
languageVariants:
- self: {id: 1411, title: 'FR: Groups', language: 1}
- self: {id: 1412, title: 'FR-CA: Groups', language: 2}
- self: {id: 1500, title: 'Internal'}
children:
- self: {id: 1510, title: 'Whitepapers', visitorGroups: -2, extendToSubpages: true}
children:
- self: {id: 1511, title: 'Products'}
- self: {id: 1512, title: 'Solutions', visitorGroups: 10}
- self: {id: 1515, title: 'Research', visitorGroups: 20}
- self: {id: 1520, title: 'Forecasts', visitorGroups: 20, extendToSubpages: true}
children:
- self: {id: 1521, title: 'Current Year'}
- self: {id: 1522, title: 'Next Year'}
- self: {id: 1523, title: 'Five Years'}
- self: {id: 1600, title: 'About us'}
- self: {id: 1700, title: 'Announcements & News', type: *pageMount, mount: 7100}
- self: {id: 404, title: 'Page not found'}
entities:
content:
- self: {title: 'EN: Page not found', type: *contentText}
- self: {id: 1930, title: 'Our Blog', type: *pageShortcut, shortcut: 2000}
- version: {id: 1950, title: 'EN: Goodbye', workspace: 1}
- self: {id: 1990, title: 'Storage', type: *pageFolder}
entities:
visitorGroup:
- self: {id: 10, title: 'Customers'}
- self: {id: 20, title: 'Partners'}
visitor:
- self: {id: 1, username: 'john@doe.local', groups: '10'}
- self: {id: 2, username: 'manager@other-inc.local', groups: '20'}
- self: {id: 3, username: 'big-boss@acme-inc.local', groups: '10,20'}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment