c60a742fba7f8b6f9a5f4faf406f05143e629157
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Tests / Unit / Form / FormDataProvider / TcaSelectTreeItemsTest.php
1 <?php
2 namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Doctrine\DBAL\Driver\Statement;
18 use Prophecy\Argument;
19 use Prophecy\Prophecy\ObjectProphecy;
20 use TYPO3\CMS\Backend\Form\FormDataProvider\TcaSelectTreeItems;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\Database\Connection;
23 use TYPO3\CMS\Core\Database\ConnectionPool;
24 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
25 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
26 use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer;
27 use TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider;
28 use TYPO3\CMS\Core\Tree\TableConfiguration\TableConfigurationTree;
29 use TYPO3\CMS\Core\Utility\GeneralUtility;
30
31 /**
32 * Tests for the TcaSelectTreeItems provider.
33 *
34 * This test only covers the renderTree() method. All other methods are covered TcaSelecItemsTest
35 *
36 * @see TcaSelecItemsTest
37 */
38 class TcaSelectTreeItemsTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
39 {
40 /**
41 * Subject is not notice free, disable E_NOTICES
42 */
43 protected static $suppressNotices = true;
44
45 /**
46 * @var TcaSelectTreeItems
47 */
48 protected $subject;
49
50 /**
51 * @var array A backup of registered singleton instances
52 */
53 protected $singletonInstances = [];
54
55 /**
56 * Initializes the mock object.
57 */
58 public function setUp()
59 {
60 $this->singletonInstances = GeneralUtility::getSingletonInstances();
61 $this->subject = new TcaSelectTreeItems();
62 }
63
64 protected function tearDown()
65 {
66 GeneralUtility::purgeInstances();
67 GeneralUtility::resetSingletonInstances($this->singletonInstances);
68 parent::tearDown();
69 }
70
71 /**
72 * Setup a mock database connection with expectations for
73 * the testsuite.
74 */
75 protected function mockDatabaseConnection()
76 {
77 $connectionProphet = $this->prophesize(Connection::class);
78 $connectionProphet->quote(Argument::cetera())->will(function ($arguments) {
79 return "'" . $arguments[0] . "'";
80 });
81 $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
82 return '`' . $arguments[0] . '`';
83 });
84
85 /** @var Statement|ObjectProphecy $statementProphet */
86 $statementProphet = $this->prophesize(Statement::class);
87 $statementProphet->fetch()->shouldBeCalled();
88
89 $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class);
90 $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal());
91 $restrictionProphet->add(Argument::cetera())->willReturn($restrictionProphet->reveal());
92
93 $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
94 $queryBuilderProphet->expr()->willReturn(
95 GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
96 );
97 $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal());
98 $queryBuilderProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
99 return '`' . $arguments[0] . '`';
100 });
101
102 $connectionPoolProphet = $this->prophesize(ConnectionPool::class);
103 $connectionPoolProphet->getConnectionForTable('foreignTable')
104 ->willReturn($connectionProphet->reveal());
105 $connectionPoolProphet->getQueryBuilderForTable('foreignTable')
106 ->shouldBeCalled()
107 ->willReturn($queryBuilderProphet->reveal());
108
109 $queryBuilderProphet->select('foreignTable.uid')
110 ->shouldBeCalled()
111 ->willReturn($queryBuilderProphet->reveal());
112 $queryBuilderProphet->from('foreignTable')
113 ->shouldBeCalled()
114 ->willReturn($queryBuilderProphet->reveal());
115 $queryBuilderProphet->from('pages')
116 ->shouldBeCalled()
117 ->willReturn($queryBuilderProphet->reveal());
118 $queryBuilderProphet->where('')
119 ->shouldBeCalled()
120 ->willReturn($queryBuilderProphet->reveal());
121 $queryBuilderProphet->andWhere(' 1=1')
122 ->shouldBeCalled()
123 ->willReturn($queryBuilderProphet->reveal());
124 $queryBuilderProphet->andWhere('`pages.uid` = `foreignTable.pid`')
125 ->shouldBeCalled()
126 ->willReturn($queryBuilderProphet->reveal());
127 $queryBuilderProphet->execute()
128 ->shouldBeCalled()
129 ->willReturn($statementProphet->reveal());
130
131 // Two instances are needed due to the push/pop behavior of addInstance()
132 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
133 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
134 }
135
136 /**
137 * @test
138 */
139 public function addDataAddsTreeConfigurationForExtJs()
140 {
141 $GLOBALS['TCA']['foreignTable'] = [];
142
143 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
144 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
145 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
146 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
147
148 $this->mockDatabaseConnection();
149
150 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
151 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
152 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
153
154 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
155 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
156 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
157 $tableConfigurationTreeProphecy->setDataProvider(Argument::cetera())->shouldBeCalled();
158 $tableConfigurationTreeProphecy->setNodeRenderer(Argument::cetera())->shouldBeCalled();
159 $tableConfigurationTreeProphecy->render()->shouldBeCalled()->willReturn(['fake', 'tree', 'data']);
160
161 $input = [
162 'tableName' => 'aTable',
163 'databaseRow' => [
164 'aField' => '1'
165 ],
166 'processedTca' => [
167 'columns' => [
168 'aField' => [
169 'config' => [
170 'type' => 'select',
171 'renderType' => 'selectTree',
172 'treeConfig' => [
173 'childrenField' => 'childrenField'
174 ],
175 'foreign_table' => 'foreignTable',
176 'items' => [],
177 'maxitems' => 1
178 ],
179 ],
180 ],
181 ],
182 'selectTreeCompileItems' => true,
183 ];
184
185 $expected = $input;
186 $expected['databaseRow']['aField'] = ['1'];
187 $expected['processedTca']['columns']['aField']['config']['items'] = [
188 'fake', 'tree', 'data',
189 ];
190 $this->assertEquals($expected, $this->subject->addData($input));
191 }
192
193 /**
194 * @test
195 */
196 public function addDataHandsPageTsConfigSettingsOverToTableConfigurationTree()
197 {
198 $GLOBALS['TCA']['foreignTable'] = [];
199
200 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
201 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
202 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
203 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
204
205 $this->mockDatabaseConnection();
206
207 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
208 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
209 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
210
211 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
212 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
213 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
214 $tableConfigurationTreeProphecy->render()->willReturn([]);
215 $tableConfigurationTreeProphecy->setDataProvider(Argument::cetera())->shouldBeCalled();
216 $tableConfigurationTreeProphecy->setNodeRenderer(Argument::cetera())->shouldBeCalled();
217
218 $input = [
219 'tableName' => 'aTable',
220 'databaseRow' => [
221 'aField' => '1'
222 ],
223 'processedTca' => [
224 'columns' => [
225 'aField' => [
226 'config' => [
227 'type' => 'select',
228 'renderType' => 'selectTree',
229 'treeConfig' => [
230 'childrenField' => 'childrenField'
231 ],
232 'foreign_table' => 'foreignTable',
233 'items' => [],
234 'maxitems' => 1
235 ],
236 ],
237 ],
238 ],
239 'pageTsConfig' => [
240 'TCEFORM.' => [
241 'aTable.' => [
242 'aField.' => [
243 'config.' => [
244 'treeConfig.' => [
245 'rootUid' => '42',
246 'appearance.' => [
247 'expandAll' => 1,
248 'maxLevels' => 4,
249 'nonSelectableLevels' => '0,1',
250 ],
251 ],
252 ],
253 ],
254 ],
255 ],
256 ],
257 'selectTreeCompileItems' => true,
258 ];
259
260 $this->subject->addData($input);
261
262 $treeDataProviderProphecy->setRootUid(42)->shouldHaveBeenCalled();
263 $treeDataProviderProphecy->setExpandAll(true)->shouldHaveBeenCalled();
264 $treeDataProviderProphecy->setLevelMaximum(4)->shouldHaveBeenCalled();
265 $treeDataProviderProphecy->setNonSelectableLevelList('0,1')->shouldHaveBeenCalled();
266 }
267 }