ea5c7b7398380acf53abc6471fe2abe75599460f
[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\Tests\UnitTestCase;
28 use TYPO3\CMS\Core\Tree\TableConfiguration\DatabaseTreeDataProvider;
29 use TYPO3\CMS\Core\Tree\TableConfiguration\TableConfigurationTree;
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31
32 /**
33 * Tests for the TcaSelectTreeItems provider.
34 *
35 * This test only covers the renderTree() method. All other methods are covered TcaSelecItemsTest
36 *
37 * @see TcaSelecItemsTest
38 */
39 class TcaSelectTreeItemsTest extends UnitTestCase
40 {
41 /**
42 * @var TcaSelectTreeItems
43 */
44 protected $subject;
45
46 /**
47 * @var array A backup of registered singleton instances
48 */
49 protected $singletonInstances = [];
50
51 /**
52 * Initializes the mock object.
53 */
54 public function setUp()
55 {
56 $this->singletonInstances = GeneralUtility::getSingletonInstances();
57 $this->subject = new TcaSelectTreeItems();
58 }
59
60 protected function tearDown()
61 {
62 GeneralUtility::purgeInstances();
63 GeneralUtility::resetSingletonInstances($this->singletonInstances);
64 parent::tearDown();
65 }
66
67 /**
68 * Setup a mock database connection with expectations for
69 * the testsuite.
70 */
71 protected function mockDatabaseConnection()
72 {
73 $connectionProphet = $this->prophesize(Connection::class);
74 $connectionProphet->quote(Argument::cetera())->will(function ($arguments) {
75 return "'" . $arguments[0] . "'";
76 });
77 $connectionProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
78 return '`' . $arguments[0] . '`';
79 });
80
81 /** @var Statement|ObjectProphecy $statementProphet */
82 $statementProphet = $this->prophesize(Statement::class);
83 $statementProphet->errorInfo()->shouldBeCalled();
84 $statementProphet->fetch()->shouldBeCalled();
85
86 $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class);
87 $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal());
88 $restrictionProphet->add(Argument::cetera())->willReturn($restrictionProphet->reveal());
89
90 $queryBuilderProphet = $this->prophesize(QueryBuilder::class);
91 $queryBuilderProphet->expr()->willReturn(
92 GeneralUtility::makeInstance(ExpressionBuilder::class, $connectionProphet->reveal())
93 );
94 $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal());
95 $queryBuilderProphet->quoteIdentifier(Argument::cetera())->will(function ($arguments) {
96 return '`' . $arguments[0] . '`';
97 });
98
99 $connectionPoolProphet = $this->prophesize(ConnectionPool::class);
100 $connectionPoolProphet->getConnectionForTable('foreignTable')
101 ->willReturn($connectionProphet->reveal());
102 $connectionPoolProphet->getQueryBuilderForTable('foreignTable')
103 ->shouldBeCalled()
104 ->willReturn($queryBuilderProphet->reveal());
105
106 $queryBuilderProphet->select('foreignTable.uid')
107 ->shouldBeCalled()
108 ->willReturn($queryBuilderProphet->reveal());
109 $queryBuilderProphet->from('foreignTable')
110 ->shouldBeCalled()
111 ->willReturn($queryBuilderProphet->reveal());
112 $queryBuilderProphet->from('pages')
113 ->shouldBeCalled()
114 ->willReturn($queryBuilderProphet->reveal());
115 $queryBuilderProphet->where('')
116 ->shouldBeCalled()
117 ->willReturn($queryBuilderProphet->reveal());
118 $queryBuilderProphet->andWhere(' 1=1')
119 ->shouldBeCalled()
120 ->willReturn($queryBuilderProphet->reveal());
121 $queryBuilderProphet->andWhere('`pages.uid` = `foreignTable.pid`')
122 ->shouldBeCalled()
123 ->willReturn($queryBuilderProphet->reveal());
124 $queryBuilderProphet->execute()
125 ->shouldBeCalled()
126 ->willReturn($statementProphet->reveal());
127
128 # Two instances are needed due to the push/pop behavior of addInstance()
129 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
130 GeneralUtility::addInstance(ConnectionPool::class, $connectionPoolProphet->reveal());
131 }
132
133 /**
134 * @test
135 */
136 public function addDataAddsTreeConfigurationForExtJs()
137 {
138 $GLOBALS['TCA']['foreignTable'] = [];
139
140 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
141 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
142 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
143 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
144
145 $this->mockDatabaseConnection();
146
147 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
148 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
149 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
150
151 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
152 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
153 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
154 $tableConfigurationTreeProphecy->setDataProvider(Argument::cetera())->shouldBeCalled();
155 $tableConfigurationTreeProphecy->setNodeRenderer(Argument::cetera())->shouldBeCalled();
156 $tableConfigurationTreeProphecy->render()->shouldBeCalled()->willReturn(['fake', 'tree', 'data']);
157
158 $input = [
159 'tableName' => 'aTable',
160 'databaseRow' => [
161 'aField' => '1'
162 ],
163 'processedTca' => [
164 'columns' => [
165 'aField' => [
166 'config' => [
167 'type' => 'select',
168 'renderType' => 'selectTree',
169 'treeConfig' => [
170 'childrenField' => 'childrenField'
171 ],
172 'foreign_table' => 'foreignTable',
173 'items' => [],
174 'maxitems' => 1
175 ],
176 ],
177 ],
178 ],
179 ];
180
181 $expected = $input;
182 $expected['databaseRow']['aField'] = ['1'];
183 $expected['processedTca']['columns']['aField']['config']['treeData'] = [
184 'items' => [['fake', 'tree', 'data']],
185 'selectedNodes' => []
186 ];
187 $this->assertEquals($expected, $this->subject->addData($input));
188 }
189
190 /**
191 * @test
192 */
193 public function addDataHandsPageTsConfigSettingsOverToTableConfigurationTree()
194 {
195 $GLOBALS['TCA']['foreignTable'] = [];
196
197 /** @var BackendUserAuthentication|ObjectProphecy $backendUserProphecy */
198 $backendUserProphecy = $this->prophesize(BackendUserAuthentication::class);
199 $GLOBALS['BE_USER'] = $backendUserProphecy->reveal();
200 $backendUserProphecy->getPagePermsClause(Argument::cetera())->willReturn(' 1=1');
201
202 $this->mockDatabaseConnection();
203
204 /** @var DatabaseTreeDataProvider|ObjectProphecy $treeDataProviderProphecy */
205 $treeDataProviderProphecy = $this->prophesize(DatabaseTreeDataProvider::class);
206 GeneralUtility::addInstance(DatabaseTreeDataProvider::class, $treeDataProviderProphecy->reveal());
207
208 /** @var TableConfigurationTree|ObjectProphecy $treeDataProviderProphecy */
209 $tableConfigurationTreeProphecy = $this->prophesize(TableConfigurationTree::class);
210 GeneralUtility::addInstance(TableConfigurationTree::class, $tableConfigurationTreeProphecy->reveal());
211
212 $input = [
213 'tableName' => 'aTable',
214 'databaseRow' => [
215 'aField' => '1'
216 ],
217 'processedTca' => [
218 'columns' => [
219 'aField' => [
220 'config' => [
221 'type' => 'select',
222 'renderType' => 'selectTree',
223 'treeConfig' => [
224 'childrenField' => 'childrenField'
225 ],
226 'foreign_table' => 'foreignTable',
227 'items' => [],
228 'maxitems' => 1
229 ],
230 ],
231 ],
232 ],
233 'pageTsConfig' => [
234 'TCEFORM.' => [
235 'aTable.' => [
236 'aField.' => [
237 'config.' => [
238 'treeConfig.' => [
239 'rootUid' => '42',
240 'appearance.' => [
241 'expandAll' => 1,
242 'maxLevels' => 4,
243 'nonSelectableLevels' => '0,1',
244 ],
245 ],
246 ],
247 ],
248 ],
249 ],
250 ],
251 ];
252
253 $this->subject->addData($input);
254
255 $treeDataProviderProphecy->setRootUid(42)->shouldHaveBeenCalled();
256 $treeDataProviderProphecy->setExpandAll(true)->shouldHaveBeenCalled();
257 $treeDataProviderProphecy->setLevelMaximum(4)->shouldHaveBeenCalled();
258 $treeDataProviderProphecy->setNonSelectableLevelList('0,1')->shouldHaveBeenCalled();
259 }
260 }