Skip to content

Commit

Permalink
[BUGFIX] Properly handle array key access in ExtendedTemplateService
Browse files Browse the repository at this point in the history
This fixes the ExtendedTemplateService->ext_getSetup()
method, which now properly handles array key accesses.

A new early return now also checks for an empty
key and returns the whole setup in this case.
This is a special case, needed for e.g. the
object browser, to still show the full setup
when object lists exist.

Resolves: #94971
Releases: master
Change-Id: I7b6615022ba59dc99929b05744c1cb33805098aa
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/71461
Tested-by: core-ci <typo3@b13.com>
Tested-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Tested-by: Jochen <rothjochen@gmail.com>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Tymoteusz Motylewski <t.motylewski@gmail.com>
Reviewed-by: Jochen <rothjochen@gmail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
  • Loading branch information
o-ba authored and bmack committed Oct 8, 2021
1 parent c952515 commit 4f7416a
Show file tree
Hide file tree
Showing 3 changed files with 240 additions and 9 deletions.
26 changes: 17 additions & 9 deletions typo3/sysext/core/Classes/TypoScript/ExtendedTemplateService.php
Expand Up @@ -283,21 +283,29 @@ public function generateConfig_constants()
/**
* @param array $theSetup
* @param string $theKey
* @return array
* @return array{0: array, 1: string}
*/
public function ext_getSetup($theSetup, $theKey)
{
$theKey = trim((string)$theKey);
if (empty($theKey)) {
// Early return the whole setup in case key is empty
return [(array)$theSetup, ''];
}
// 'a.b.c' --> ['a', 'b.c']
$parts = explode('.', $theKey, 2);
if ((string)$parts[0] !== '' && is_array($theSetup[$parts[0] . '.'] ?? false)) {
if (trim($parts[1]) !== '') {
return $this->ext_getSetup($theSetup[$parts[0] . '.'], trim($parts[1]));
$pathSegment = $parts[0] ?? '';
$pathRest = trim($parts[1] ?? '');
if ($pathSegment !== '' && is_array($theSetup[$pathSegment . '.'] ?? false)) {
if ($pathRest !== '') {
// Current path segment is a sub array, check it recursively by applying the rest of the key
return $this->ext_getSetup($theSetup[$pathSegment . '.'], $pathRest);
}
return [$theSetup[$parts[0] . '.'], $theSetup[$parts[0]]];
}
if (trim($theKey) !== '') {
return [[], $theSetup[$theKey]];
// No further path to evaluate, return current setup and the value for the current path segment - if any
return [$theSetup[$pathSegment . '.'], $theSetup[$pathSegment] ?? ''];
}
return [$theSetup, ''];
// Return the key value - if any - along with an empty setup since no sub array exists
return [[], $theSetup[$theKey] ?? ''];
}

/**
Expand Down
Expand Up @@ -208,4 +208,32 @@ public function searchInTypoScriptObjectBrowser(ApplicationTester $I): void
$I->waitForText('CONSTANTS ROOT');
$I->seeInSource('<strong class="text-danger">styles</strong>');
}

/**
* @depends addANewSiteTemplate
*/
public function useObjectListInObjectBrowser(ApplicationTester $I): void
{
$I->wantTo('Open the TypoScript Object Browser and use the object list.');
$I->switchToMainFrame();
$I->clickWithLeftButton('//*[text()=\'styleguide TCA demo\']');
$I->switchToContentFrame();

$I->amGoingTo('Switch to object browser.');
$I->selectOption('.t3-js-jumpMenuBox', 'TypoScript Object Browser');
$I->waitForText('CONSTANTS ROOT');
$I->selectOption('select[name="SET[ts_browser_type]"]', 'Setup');
$I->waitForText('SETUP ROOT');
$I->click('tt_content');
$I->waitForText('Edit object/property value');

$I->amGoingTo('add tt_content to object list');
$I->click('Add key "tt_content" to Object List');
$I->see('Remove key from OL');
$I->see('key');

$I->amGoingTo('verify "all" can still be selected and shows full setup.');
$I->selectOption('select[name="SET[ts_browser_toplevel_setup]"]', 'all');
$I->seeInSource('<i class="text-muted"># Content element rendering</i>');
}
}
@@ -0,0 +1,195 @@
<?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\Core\Tests\Unit\TypoScript;

use PHPUnit\Framework\MockObject\MockObject;
use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

/**
* Test case
*/
class ExtendedTemplateServiceTest extends UnitTestCase
{

/**
* @var ExtendedTemplateService|MockObject|AccessibleObjectInterface
*/
protected $extendedTemplateServiceMock;

/**
* Set up
*/
protected function setUp(): void
{
parent::setUp();
$this->extendedTemplateServiceMock = $this->getAccessibleMock(
ExtendedTemplateService::class,
null,
[],
'',
false
);
}

/**
* @dataProvider ext_getSetupDataProvider
* @test
*/
public function ext_getSetupTest($setup, $key, $expected): void
{
$actual = $this->extendedTemplateServiceMock->ext_getSetup($setup, $key);
self::assertEquals($expected, $actual);
}

public function ext_getSetupDataProvider(): array
{
return [
'empty setup and key' => [
[],
'',
[[], ''],
],
'empty setup and not empty key' => [
[],
'key',
[[], ''],
],
'empty key' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '',
'expected' => [
[
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'',
],
],
'special key "0" which is considered as empty' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '0',
'expected' => [
[
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'',
],
],
'not empty key - 1st level' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '10',
'expected' => [
[
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'TEXT',
],
],
'not empty key - 2nd level' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '10.foo',
'expected' => [
[
'bar' => 5,
],
'',
],
],
'not empty key - 3rd level - leaf' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '10.foo.bar',
'expected' => [
[],
'5',
],
],
'not empty key - 4th, non existing level' => [
'typoScriptSetup' => [
'10.' => [
'value' => 'Hello World!',
'foo.' => [
'bar' => 5,
],
],
'10' => 'TEXT',
],
'key' => '10.foo.bar.baz',
'expected' => [
[],
'',
],
],
];
}
}

0 comments on commit 4f7416a

Please sign in to comment.