diff --git a/Classes/Provider/PageProvider.php b/Classes/Provider/PageProvider.php
index 58cda02f..9f48e69d 100644
--- a/Classes/Provider/PageProvider.php
+++ b/Classes/Provider/PageProvider.php
@@ -11,6 +11,7 @@
use FluidTYPO3\Fluidpages\Controller\PageControllerInterface;
use FluidTYPO3\Fluidpages\Service\ConfigurationService;
use FluidTYPO3\Fluidpages\Service\PageService;
+use FluidTYPO3\Fluidpages\UserFunction\LayoutSelect;
use FluidTYPO3\Flux\Form;
use FluidTYPO3\Flux\Provider\AbstractProvider;
use FluidTYPO3\Flux\Provider\ProviderInterface;
@@ -106,6 +107,15 @@ public function injectPageService(PageService $pageService)
$this->pageService = $pageService;
}
+ /**
+ * @param LayoutSelect $layoutSelect
+ * @return void
+ */
+ public function injectLayoutSelect(LayoutSelect $layoutSelect)
+ {
+ $this->layoutSelect = $layoutSelect;
+ }
+
/**
* @param ConfigurationService $pageConfigurationService
* @return void
@@ -199,8 +209,9 @@ public function getControllerActionFromRecord(array $row)
*/
public function getControllerActionReferenceFromRecord(array $row)
{
- if (true === empty($row[self::FIELD_ACTION_MAIN])) {
- $row = $this->pageService->getPageTemplateConfiguration($row['uid']);
+ $useFluidpages = $this->layoutSelect->isFluidpagesBackendLayout($row['backend_layout']);
+ if (true === empty($row[self::FIELD_ACTION_MAIN]) || false === $useFluidpages) {
+ $row = $this->layoutSelect->getPageTemplateConfiguration($row['uid']);
}
return $row[self::FIELD_ACTION_MAIN];
}
diff --git a/Classes/Service/PageService.php b/Classes/Service/PageService.php
index eb942629..b93d8e28 100755
--- a/Classes/Service/PageService.php
+++ b/Classes/Service/PageService.php
@@ -8,6 +8,7 @@
* LICENSE.md file that was distributed with this source code.
*/
+use FluidTYPO3\Fluidpages\UserFunction\LayoutSelect;
use FluidTYPO3\Flux\Form;
use FluidTYPO3\Flux\Service\WorkspacesAwareRecordService;
use FluidTYPO3\Flux\Utility\ExtensionNamingUtility;
@@ -97,63 +98,12 @@ public function injectWorkspacesAwareRecordService(WorkspacesAwareRecordService
* @param integer $pageUid
* @return array|NULL
* @api
+ * @deprecated
*/
public function getPageTemplateConfiguration($pageUid)
{
- $pageUid = (integer) $pageUid;
- if (1 > $pageUid) {
- return null;
- }
- $cacheId = 'fluidpages-template-configuration-' . $pageUid;
- $runtimeCache = $this->getRuntimeCache();
- $fromCache = $runtimeCache->get($cacheId);
- if ($fromCache) {
- return $fromCache;
- }
- $fieldList = 'tx_fed_page_controller_action_sub,t3ver_oid,pid,uid';
- $page = $this->workspacesAwareRecordService->getSingle(
- 'pages',
- 'tx_fed_page_controller_action,' . $fieldList,
- $pageUid
- );
-
- // Initialize with possibly-empty values and loop root line
- // to fill values as they are detected.
- $resolvedMainTemplateIdentity = $page['tx_fed_page_controller_action'];
- $resolvedSubTemplateIdentity = $page['tx_fed_page_controller_action_sub'];
- do {
- $containsSubDefinition = (false !== strpos($page['tx_fed_page_controller_action_sub'], '->'));
- $isCandidate = ((integer) $page['uid'] !== $pageUid);
- if (true === $containsSubDefinition && true === $isCandidate) {
- $resolvedSubTemplateIdentity = $page['tx_fed_page_controller_action_sub'];
- if (true === empty($resolvedMainTemplateIdentity)) {
- // Conditions met: current page is not $pageUid, original page did not
- // contain a "this page" layout, current rootline page has "sub" selection.
- // Then, set our "this page" value to use the "sub" selection that was detected.
- $resolvedMainTemplateIdentity = $resolvedSubTemplateIdentity;
- }
- break;
- }
- // Note: 't3ver_oid' is analysed in order to make versioned records inherit the original record's
- // configuration as an emulated first parent page.
- $resolveParentPageUid = (integer) (0 > $page['pid'] ? $page['t3ver_oid'] : $page['pid']);
- $page = $this->workspacesAwareRecordService->getSingle(
- 'pages',
- $fieldList,
- $resolveParentPageUid
- );
- } while (null !== $page);
- if (true === empty($resolvedMainTemplateIdentity) && true === empty($resolvedSubTemplateIdentity)) {
- // Neither directly configured "this page" nor inherited "sub" contains a valid value;
- // no configuration was detected at all.
- return null;
- }
- $configurarion = [
- 'tx_fed_page_controller_action' => $resolvedMainTemplateIdentity,
- 'tx_fed_page_controller_action_sub' => $resolvedSubTemplateIdentity
- ];
- $runtimeCache->set($cacheId, $configurarion);
- return $configurarion;
+ $layoutSelect = GeneralUtility::makeInstance(LayoutSelect::class);
+ return $layoutSelect->getPageTemplateConfiguration($pageUid);
}
/**
diff --git a/Classes/UserFunction/LayoutSelect.php b/Classes/UserFunction/LayoutSelect.php
new file mode 100644
index 00000000..9f1565b7
--- /dev/null
+++ b/Classes/UserFunction/LayoutSelect.php
@@ -0,0 +1,182 @@
+getPageTemplateConfiguration($parameters['record']['uid']);
+ if (null === $conf) {
+ return false;
+ }
+
+ if ($sub) {
+ return false === empty($conf['tx_fed_page_controller_action_sub']);
+ } else {
+ return false === empty($conf['tx_fed_page_controller_action']);
+ }
+ }
+
+ /**
+ * Process RootLine to find first usable, configured Fluid Page Template.
+ * WARNING: do NOT use the output of this feature to overwrite $row - the
+ * record returned may or may not be the same record as defined in $id.
+ *
+ * @param integer $pageUid
+ * @return array|NULL Array with two keys:
+ * - tx_fed_page_controller_action
+ * - tx_fed_page_controller_action_sub
+ * @api
+ */
+ public function getPageTemplateConfiguration($pageUid)
+ {
+ $pageUid = (integer) $pageUid;
+ if (1 > $pageUid) {
+ return null;
+ }
+ $cacheId = 'fluidpages-template-configuration-' . $pageUid;
+ $runtimeCache = $this->getRuntimeCache();
+ $fromCache = $runtimeCache->get($cacheId);
+ if ($fromCache) {
+ return $fromCache;
+ }
+ $fieldList = 'tx_fed_page_controller_action_sub,backend_layout,backend_layout_next_level,t3ver_oid,pid,uid';
+ $page = $this->getWorkspacesAwareRecordService()->getSingle(
+ 'pages',
+ 'tx_fed_page_controller_action,' . $fieldList,
+ $pageUid
+ );
+
+ $checkUsage = true;
+ $useMainTemplate = $this->isFluidpagesBackendLayout($page['backend_layout']);
+ $useSubTemplate = $this->isFluidpagesBackendLayout($page['backend_layout_next_level']);
+ $mainTemplate = $page['tx_fed_page_controller_action'];
+ $subTemplate = $page['tx_fed_page_controller_action_sub'];
+ $isFirstPage = true;
+
+ do {
+ if (false === $isFirstPage) {
+ if ($checkUsage) {
+ if ($this->isFluidpagesBackendLayout($page['backend_layout_next_level'])) {
+ $useMainTemplate = true;
+ $useSubTemplate = true;
+ } else if (false === empty($page['backend_layout_next_level'])) {
+ //we have a different layout in between, so do not look further up
+ $checkUsage = false;
+ }
+ }
+ $containsSubDefinition = (false !== strpos($page['tx_fed_page_controller_action_sub'], '->'));
+ if ($containsSubDefinition) {
+ if (empty($mainTemplate)) {
+ $mainTemplate = $page['tx_fed_page_controller_action_sub'];
+ }
+ if (empty($subTemplate)) {
+ $subTemplate = $page['tx_fed_page_controller_action_sub'];
+ }
+ }
+ }
+ // Note: 't3ver_oid' is analysed in order to make versioned records inherit the original record's
+ // configuration as an emulated first parent page.
+ $resolveParentPageUid = (integer) (0 > $page['pid'] ? $page['t3ver_oid'] : $page['pid']);
+ $page = $this->getWorkspacesAwareRecordService()->getSingle(
+ 'pages',
+ $fieldList,
+ $resolveParentPageUid
+ );
+ $isFirstPage = false;
+ } while ($page);
+
+ if (empty($mainTemplate)) {
+ $useMainTemplate = false;
+ }
+ if (empty($subTemplate)) {
+ $useSubTemplate = false;
+ }
+ if (false === $useMainTemplate && false === $useSubTemplate) {
+ //BC return value
+ return null;
+ }
+ $configuration = [
+ 'tx_fed_page_controller_action' => $useMainTemplate ? $mainTemplate : null,
+ 'tx_fed_page_controller_action_sub' => $useSubTemplate ? $subTemplate : null
+ ];
+ $runtimeCache->set($cacheId, $configuration);
+ return $configuration;
+ }
+
+ /**
+ * Determine if the given backend layout string is a fluidpages layout
+ *
+ * @param string $belayout Page row backend_layout value
+ *
+ * @return boolean True if fluidpages should be used to render
+ */
+ public function isFluidpagesBackendLayout($belayout)
+ {
+ return substr($belayout, 0, 12) == 'fluidpages__';
+ }
+
+ /**
+ * @return \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend
+ */
+ protected function getRuntimeCache()
+ {
+ return GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime');
+ }
+
+ /**
+ * @return WorkspacesAwareRecordService
+ */
+ protected function getWorkspacesAwareRecordService()
+ {
+ if (null === $this->workspacesAwareRecordService) {
+ $this->workspacesAwareRecordService = GeneralUtility::makeInstance(ObjectManager::class)
+ ->get(WorkspacesAwareRecordService::class);
+ }
+ return $this->workspacesAwareRecordService;
+ }
+
+ /**
+ * Used in unit tests.
+ *
+ * @param WorkspacesAwareRecordService $workspacesAwareRecordService
+ *
+ * @return void
+ */
+ public function setWorkspacesAwareRecordService(WorkspacesAwareRecordService $workspacesAwareRecordService)
+ {
+ $this->workspacesAwareRecordService = $workspacesAwareRecordService;
+ }
+}
+?>
diff --git a/Configuration/TCA/Overrides/pages.php b/Configuration/TCA/Overrides/pages.php
index 7c6058a1..61418c5a 100644
--- a/Configuration/TCA/Overrides/pages.php
+++ b/Configuration/TCA/Overrides/pages.php
@@ -17,7 +17,8 @@
'disabled' => false
]
]
- ]
+ ],
+ 'displayCond' => 'USER:FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect->doShowPageConfiguration:0',
],
'tx_fed_page_controller_action_sub' => [
'exclude' => 1,
@@ -32,7 +33,8 @@
'disabled' => false
]
]
- ]
+ ],
+ 'displayCond' => 'USER:FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect->doShowPageConfiguration:1',
],
'tx_fed_page_flexform' => [
'exclude' => 1,
@@ -42,7 +44,8 @@
'ds' => [
'default' => ''
]
- ]
+ ],
+ 'displayCond' => 'USER:FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect->doShowPageConfiguration:0',
],
'tx_fed_page_flexform_sub' => [
'exclude' => 1,
@@ -52,7 +55,8 @@
'ds' => [
'default' => ''
]
- ]
+ ],
+ 'displayCond' => 'USER:FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect->doShowPageConfiguration:1',
],
]);
diff --git a/Tests/Unit/Provider/PageProviderTest.php b/Tests/Unit/Provider/PageProviderTest.php
index 161e59e5..680fd0af 100644
--- a/Tests/Unit/Provider/PageProviderTest.php
+++ b/Tests/Unit/Provider/PageProviderTest.php
@@ -81,7 +81,13 @@ public function testGetTemplatePathAndFilename()
$instance = new PageProvider();
$instance->setTemplatePaths(array('templateRootPaths' => array('EXT:fluidpages/Tests/Fixtures/Templates/')));
$instance->injectPageService($service);
+
+ /** @var LayoutSelect $layoutSelectMock */
+ $layoutSelectMock = $this->getMockBuilder('FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect')->setMethods(array('getPageTemplateConfiguration'))->getMock();
+ $instance->injectLayoutSelect($layoutSelectMock);
+
$record = array(
+ 'backend_layout' => 'fluidpages__fluidpages',
$fieldName => 'Fluidpages->dummy',
);
$service->expects($this->any())->method('getPageTemplateConfiguration')->willReturn($record);
@@ -158,6 +164,10 @@ public function testGetControllerActionFromRecord(array $record, $fieldName, $ex
/** @var PageService $service */
$service = $this->getMockBuilder('FluidTYPO3\\Fluidpages\\Service\\PageService')->setMethods(array('getPageTemplateConfiguration'))->getMock();
$instance->injectPageService($service);
+
+ /** @var LayoutSelect $layoutSelectMock */
+ $layoutSelectMock = $this->getMockBuilder('FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect')->setMethods(array('getPageTemplateConfiguration'))->getMock();
+ $instance->injectLayoutSelect($layoutSelectMock);
}
if (true === $expectsMessage) {
/** @var ConfigurationService|\PHPUnit_Framework_MockObject_MockObject $configurationService */
@@ -177,11 +187,86 @@ public function getControllerActionFromRecordTestValues()
{
return array(
array(array('doktype' => PageControllerInterface::DOKTYPE_RAW), '', false, 'raw'),
- array(array('doktype' => 0, 'tx_fed_page_controller_action' => ''), 'tx_fed_page_flexform', true, 'default'),
- array(array('doktype' => 0, 'tx_fed_page_controller_action' => 'fluidpages->action'), 'tx_fed_page_flexform', false, 'action'),
+ array(array('doktype' => 0, 'backend_layout' => 'fluidpages__fluidpages', 'tx_fed_page_controller_action' => ''), 'tx_fed_page_flexform', true, 'default'),
+ array(array('doktype' => 0, 'backend_layout' => 'fluidpages__fluidpages', 'tx_fed_page_controller_action' => 'fluidpages->action'), 'tx_fed_page_flexform', false, 'action'),
);
}
+ /**
+ * @dataProvider getControllerActionReferenceFromRecordTestValues
+ *
+ * @param array $record Page row
+ * @param mixed $calcRow Row data calculated by pageService->getPageTemplateConfiguration
+ * @param mixed $expected Expected return value
+ */
+ public function testGetControllerActionReferenceFromRecord(array $record, $calcRow, $expected)
+ {
+ $instance = new PageProvider();
+ /** @var LayoutSelect $layoutSelectMock */
+ $layoutSelectMock = $this->getMockBuilder('FluidTYPO3\\Fluidpages\\UserFunction\\LayoutSelect')->setMethods(array('getPageTemplateConfiguration'))->getMock();
+ $layoutSelectMock->expects($this->any())
+ ->method('getPageTemplateConfiguration')
+ ->will($this->returnValue($calcRow));
+ $instance->injectLayoutSelect($layoutSelectMock);
+
+ $result = $instance->getControllerActionReferenceFromRecord($record);
+ $this->assertEquals($expected, $result);
+ }
+
+ /**
+ * Data provider for testGetControllerActionReferenceFromRecord()
+ *
+ * @return array
+ */
+ public function getControllerActionReferenceFromRecordTestValues()
+ {
+ return [
+ 'no action' => [
+ [
+ 'tx_fed_page_controller_action' => '',
+ ],
+ null,
+ null
+ ],
+ 'normal action' => [
+ [
+ 'tx_fed_page_controller_action' => 'test1->test1',
+ 'backend_layout' => 'fluidpages__foo',
+ ],
+ [],
+ 'test1->test1'
+ ],
+ 'no action, result from pageService' => [
+ [
+ 'tx_fed_page_controller_action' => '',
+ 'backend_layout' => 'fluidpages__bar',
+ ],
+ [
+ 'tx_fed_page_controller_action' => 'test1->test1',
+ ],
+ 'test1->test1'
+ ],
+ 'no backend layout' => [
+ [
+ 'tx_fed_page_controller_action' => 'test1->test1',
+ 'backend_layout' => '',
+ ],
+ null,
+ null
+ ],
+ 'no backend layout, result from pageService' => [
+ [
+ 'tx_fed_page_controller_action' => 'test1->test1',
+ 'backend_layout' => '',
+ ],
+ [
+ 'tx_fed_page_controller_action' => 'test2->test2'
+ ],
+ 'test2->test2'
+ ],
+ ];
+ }
+
public function testGetFlexFormValuesReturnsCollectedDataWhenEncounteringNullForm()
{
$tree = array(
diff --git a/Tests/Unit/Service/PageServiceTest.php b/Tests/Unit/Service/PageServiceTest.php
index b11f99b2..0d434957 100644
--- a/Tests/Unit/Service/PageServiceTest.php
+++ b/Tests/Unit/Service/PageServiceTest.php
@@ -40,47 +40,6 @@ public function getPageFlexFormSourceWithZeroUidReturnsNull()
$this->assertNull($this->getPageService()->getPageFlexFormSource(0));
}
- /**
- * @test
- */
- public function getPageTemplateConfigurationWithZeroUidReturnsNull()
- {
- $this->assertNull($this->getPageService()->getPageTemplateConfiguration(0));
- }
-
- /**
- * @dataProvider getPageTemplateConfigurationTestValues
- * @param array $records
- * @param array|NULL $expected
- */
- public function testGetPageTemplateConfiguration(array $records, $expected)
- {
- /** @var WorkspacesAwareRecordService|\PHPUnit_Framework_MockObject_MockObject $service */
- $service = $this->getMockBuilder('FluidTYPO3\\Flux\\Service\\WorkspacesAwareRecordService')->setMethods(array('getSingle'))->getMock();
- foreach ($records as $index => $record) {
- $service->expects($this->at($index))->method('getSingle')->willReturn($record);
- }
- $instance = new PageService();
- $instance->injectWorkspacesAwareRecordService($service);
- $result = $instance->getPageTemplateConfiguration(1);
- $this->assertEquals($expected, $result);
- }
-
- /**
- * @return array
- */
- public function getPageTemplateConfigurationTestValues()
- {
- $m = 'tx_fed_page_controller_action';
- $s = 'tx_fed_page_controller_action_sub';
- return array(
- array(array(array()), null),
- array(array(array($m => '', $s => '')), null),
- array(array(array($m => 'test1->test1', $s => 'test2->test2')), array($m => 'test1->test1', $s => 'test2->test2')),
- array(array(array($m => ''), array($s => 'test2->test2')), array($m => 'test2->test2', $s => 'test2->test2'))
- );
- }
-
/**
* @return void
*/
diff --git a/Tests/Unit/UserFunction/LayoutSelectTest.php b/Tests/Unit/UserFunction/LayoutSelectTest.php
new file mode 100644
index 00000000..e99c3567
--- /dev/null
+++ b/Tests/Unit/UserFunction/LayoutSelectTest.php
@@ -0,0 +1,168 @@
+assertNull($this->getLayoutSelect()->getPageTemplateConfiguration(0));
+ }
+
+ /**
+ * @dataProvider getPageTemplateConfigurationTestValues
+ * @param array $records
+ * @param array|NULL $expected
+ */
+ public function testGetPageTemplateConfiguration(array $records, $expected)
+ {
+ /** @var WorkspacesAwareRecordService|\PHPUnit_Framework_MockObject_MockObject $service */
+ $service = $this->getMockBuilder('FluidTYPO3\\Flux\\Service\\WorkspacesAwareRecordService')->setMethods(array('getSingle'))->getMock();
+ foreach ($records as $index => $record) {
+ //automatically set page uid
+ $record['uid'] = $index + 1;
+ $record['pid'] = $index + 2;
+ $service->expects($this->at($index))->method('getSingle')->willReturn($record);
+ }
+ $instance = new LayoutSelect();
+ $instance->setWorkspacesAwareRecordService($service);
+ $result = $instance->getPageTemplateConfiguration(1);
+ $this->assertEquals($expected, $result);
+ }
+
+ /**
+ * @return array
+ */
+ public function getPageTemplateConfigurationTestValues()
+ {
+ $b = 'backend_layout';
+ $bs = 'backend_layout_next_level';
+ $a = 'tx_fed_page_controller_action';
+ $as = 'tx_fed_page_controller_action_sub';
+ $bfp = 'fluidpages__fluidpages';
+ return [
+ 'no data at all' => [
+ [[]],
+ null
+ ],
+ 'empty actions' => [
+ [
+ [$a => '', $as => '', $b => $bfp, $bs => $bfp]
+ ],
+ null
+ ],
+ 'controller action on page itself' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => $bfp, $bs => $bfp]
+ ],
+ [$a => 'test->self', $as => 'test->selfsub']
+ ],
+ 'sub controller action on parent page' => [
+ [
+ //pages are listed in reverse order, root level last
+ [$a => '', $b => $bfp, $bs => $bfp],
+ [$as => 'test->selfsub', $b => $bfp, $bs => $bfp]
+ ],
+ [$a => 'test->selfsub', $as => 'test->selfsub']
+ ],
+ 'no backend layout configured' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => '', $bs => ''],
+ ],
+ null
+ ],
+ 'backend layout configured only for parent page' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => '' , $bs => ''],
+ [$a => 'test->root', $as => 'test->rootsub', $b => $bfp, $bs => ''],
+ ],
+ null
+ ],
+ 'backend layout configured on parent page' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => '', $bs => ''],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => $bfp],
+ ],
+ [$a => 'test->self', $as => 'test->selfsub'],
+ ],
+ 'backend layout configured on parent page #2' => [
+ [
+ [$a => '' , $as => '' , $b => '', $bs => ''],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => $bfp],
+ ],
+ [$a => 'test->rootsub', $as => 'test->rootsub'],
+ ],
+ 'different backend layout in between' => [
+ [
+ [$a => '' , $as => '' , $b => '', $bs => ''],
+ [$a => '' , $as => '' , $b => '', $bs => 'templavoila'],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => $bfp],
+ ],
+ null
+ ],
+ 'self backend layout, but different sub backend layout in between' => [
+ [
+ [$a => '' , $as => '' , $b => $bfp, $bs => ''],
+ [$a => '' , $as => '' , $b => '', $bs => 'templavoila'],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => $bfp],
+ ],
+ [$a => 'test->rootsub', $as => null]
+ ],
+ 'action and backend layout on different levels: action higher' => [
+ [
+ [$a => '' , $as => '' , $b => '', $bs => ''],
+ [$a => '' , $as => '' , $b => '', $bs => $bfp],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => ''],
+ ],
+ [$a => 'test->rootsub', $as => 'test->rootsub']
+ ],
+ 'action and backend layout on different levels: backend layout higher' => [
+ [
+ [$a => '' , $as => '' , $b => '', $bs => ''],
+ [$a => 'test->mid', $as => 'test->midsub', $b => '', $bs => ''],
+ [$a => '' , $as => '' , $b => '', $bs => $bfp],
+ ],
+ [$a => 'test->midsub', $as => 'test->midsub']
+ ],
+ 'only sub backend layout, but both actions, no parents' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => '', $bs => $bfp],
+ ],
+ [$a => null, $as => 'test->selfsub']
+ ],
+ 'only sub backend layout, but both actions, parents' => [
+ [
+ [$a => 'test->self', $as => 'test->selfsub', $b => '', $bs => $bfp],
+ [$a => 'test->root', $as => 'test->rootsub', $b => '', $bs => ''],
+ ],
+ [$a => null, $as => 'test->selfsub']
+ ],
+ ];
+ }
+}