Skip to content
Snippets Groups Projects
Commit 85836c4c authored by Oliver Hader's avatar Oliver Hader Committed by Christian Kuhn
Browse files

[BUGFIX] Localization State does not properly sanitize and enrich

The Localization State object has an incomplete assignment in the
constructor - sanitize processing is overridden by enrich processing,
however both should be combined instead.

The current side-effects were, that
* localization state could contain fields that were not defined in TCA
  having support for the `allowLanguageSynchronization` setting
* state values different than `custom`, `source` or `parent` have not
  been overridden by the default `parent` value

Resolves: #82793
Releases: 8.7, master
Change-Id: I25e794736df216b17a5b8de3bc5203bd18ee9694
Reviewed-on: https://review.typo3.org/54422


Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: default avatarSusanne Moog <susanne.moog@typo3.org>
Tested-by: default avatarSusanne Moog <susanne.moog@typo3.org>
Reviewed-by: default avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: default avatarChristian Kuhn <lolli@schwarzbu.ch>
parent cb1e38e1
Branches
Tags
No related merge requests found
......@@ -82,7 +82,7 @@ class State
{
return array_keys(
array_filter(
$GLOBALS['TCA'][$tableName]['columns'],
$GLOBALS['TCA'][$tableName]['columns'] ?? [],
function (array $fieldConfiguration) {
return !empty(
$fieldConfiguration['config']
......@@ -138,6 +138,15 @@ class State
*/
protected $originalStates;
/**
* @var array
*/
protected $validStates = [
self::STATE_CUSTOM,
self::STATE_SOURCE,
self::STATE_PARENT,
];
/**
* @param string $tableName
* @param array $states
......@@ -148,8 +157,9 @@ class State
$this->states = $states;
$this->originalStates = $states;
$this->states = $this->sanitize($states);
$this->states = $this->enrich($states);
$this->states = $this->enrich(
$this->sanitize($states)
);
}
/**
......@@ -311,7 +321,12 @@ class State
protected function enrich(array $states)
{
foreach (static::getFieldNames($this->tableName) as $fieldName) {
if (!empty($states[$fieldName])) {
$isValid = in_array(
$states[$fieldName] ?? null,
$this->validStates,
true
);
if ($isValid) {
continue;
}
$states[$fieldName] = static::STATE_PARENT;
......
<?php
namespace TYPO3\CMS\Core\Tests\Unit\DataHandler\Localization;
/*
* 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\DataHandling\Localization\State;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
/**
* Test case
*/
class StateTest extends UnitTestCase
{
const TABLE_NAME = 'tx_test_table';
/**
* Set up the tests
*/
protected function setUp()
{
$GLOBALS['TCA'] = [];
}
/**
* @param string $tableName
* @param array $states
*
* @test
* @dataProvider stateObjectCanBeCreatedDataProvider
*/
public function stateObjectCanBeCreated(string $tableName, array $states)
{
$subject = new State($tableName, $states);
$this->assertInstanceOf(State::class, $subject);
}
/**
* @return array
*/
public function stateObjectCanBeCreatedDataProvider(): array
{
return [
'without states' => [
static::TABLE_NAME,
[],
],
'with states' => [
static::TABLE_NAME,
['nonExistingField' => 'invalidState'],
],
];
}
/**
* @param array $states
* @param array $expected
*
* @test
* @dataProvider statesAreEnrichedAndSanitizedOnObjectCreationDataProvider
*/
public function statesAreEnrichedAndSanitizedOnObjectCreation(
array $states,
array $expected
) {
$GLOBALS['TCA'] = $this->provideTableConfiguration(
'first_field',
'second_field'
);
$subject = new State(static::TABLE_NAME, $states);
$this->assertSame(
$expected,
$subject->toArray()
);
}
/**
* @return array
*/
public function statesAreEnrichedAndSanitizedOnObjectCreationDataProvider(): array
{
return [
'empty' => [
[],
[
'first_field' => 'parent',
'second_field' => 'parent',
],
],
'invalid field only' => [
[
'invalid_field' => 'invalidState',
],
[
'first_field' => 'parent',
'second_field' => 'parent',
],
],
'first_field only, valid state' => [
[
'first_field' => 'custom',
],
[
'first_field' => 'custom',
'second_field' => 'parent',
],
],
'first_field only, invalid state' => [
[
'first_field' => 'invalidState',
],
[
'first_field' => 'parent',
'second_field' => 'parent',
],
],
'all valid fields, valid states' => [
[
'first_field' => 'custom',
'second_field' => 'parent',
],
[
'first_field' => 'custom',
'second_field' => 'parent',
],
],
'all valid fields, invalid states' => [
[
'first_field' => 'invalidState',
'second_field' => 'invalidState',
],
[
'first_field' => 'parent',
'second_field' => 'parent',
],
],
'all valid fields, valid states and invalid field' => [
[
'invalid_field' => 'invalidState',
'first_field' => 'custom',
'second_field' => 'parent',
],
[
'first_field' => 'custom',
'second_field' => 'parent',
],
],
'all valid fields, invalid states and invalid field' => [
[
'invalid_field' => 'invalidState',
'first_field' => 'invalidState',
'second_field' => 'invalidState',
],
[
'first_field' => 'parent',
'second_field' => 'parent',
],
],
];
}
/**
* @param string[] ...$fieldNames
*
* @return array
*/
private function provideTableConfiguration(string ...$fieldNames): array
{
$columnsConfiguration = [];
foreach ($fieldNames as $fieldName) {
$columnsConfiguration[$fieldName]['config']['behaviour']['allowLanguageSynchronization'] = true;
}
return [
static::TABLE_NAME => [
'columns' => $columnsConfiguration,
],
];
}
}
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