[CLEANUP] Rework/simplify copyright header and remove @package
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Mvc / Controller / MvcPropertyMappingConfigurationServiceTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Mvc\Controller;
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 /**
18 * Test case
19 */
20 class MvcPropertyMappingConfigurationServiceTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
21
22 /**
23 * Data provider for generating the list of trusted properties
24 *
25 * @return array
26 */
27 public function dataProviderForgenerateTrustedPropertiesToken() {
28 return array(
29 'Simple Case - Empty' => array(
30 array(),
31 array(),
32 ),
33 'Simple Case - Single Value' => array(
34 array('field1'),
35 array('field1' => 1),
36 ),
37 'Simple Case - Two Values' => array(
38 array('field1', 'field2'),
39 array(
40 'field1' => 1,
41 'field2' => 1
42 ),
43 ),
44 'Recursion' => array(
45 array('field1', 'field[subfield1]', 'field[subfield2]'),
46 array(
47 'field1' => 1,
48 'field' => array(
49 'subfield1' => 1,
50 'subfield2' => 1
51 )
52 ),
53 ),
54 'recursion with duplicated field name' => array(
55 array('field1', 'field[subfield1]', 'field[subfield2]', 'field1'),
56 array(
57 'field1' => 1,
58 'field' => array(
59 'subfield1' => 1,
60 'subfield2' => 1
61 )
62 ),
63 ),
64 'Recursion with un-named fields at the end (...[]). There, they should be made explicit by increasing the counter' => array(
65 array('field1', 'field[subfield1][]', 'field[subfield1][]', 'field[subfield2]'),
66 array(
67 'field1' => 1,
68 'field' => array(
69 'subfield1' => array(
70 0 => 1,
71 1 => 1
72 ),
73 'subfield2' => 1
74 )
75 ),
76 ),
77 );
78 }
79
80 /**
81 * Data Provider for invalid values in generating the list of trusted properties,
82 * which should result in an exception
83 *
84 * @return array
85 */
86 public function dataProviderForgenerateTrustedPropertiesTokenWithUnallowedValues() {
87 return array(
88 'Overriding form fields (string overridden by array) - 1' => array(
89 array('field1', 'field2', 'field2[bla]', 'field2[blubb]'),
90 ),
91 'Overriding form fields (string overridden by array) - 2' => array(
92 array('field1', 'field2[bla]', 'field2[bla][blubb][blubb]'),
93 ),
94 'Overriding form fields (array overridden by string) - 1' => array(
95 array('field1', 'field2[bla]', 'field2[blubb]', 'field2'),
96 ),
97 'Overriding form fields (array overridden by string) - 2' => array(
98 array('field1', 'field2[bla][blubb][blubb]', 'field2[bla]'),
99 ),
100 'Empty [] not as last argument' => array(
101 array('field1', 'field2[][bla]'),
102 )
103
104 );
105 }
106
107 /**
108 * @test
109 * @dataProvider dataProviderForgenerateTrustedPropertiesToken
110 */
111 public function generateTrustedPropertiesTokenGeneratesTheCorrectHashesInNormalOperation($input, $expected) {
112 $requestHashService = $this->getMock(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService::class, array('serializeAndHashFormFieldArray'));
113 $requestHashService->expects($this->once())->method('serializeAndHashFormFieldArray')->with($expected);
114 $requestHashService->generateTrustedPropertiesToken($input);
115 }
116
117 /**
118 * @test
119 * @dataProvider dataProviderForgenerateTrustedPropertiesTokenWithUnallowedValues
120 * @expectedException \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
121 */
122 public function generateTrustedPropertiesTokenThrowsExceptionInWrongCases($input) {
123 $requestHashService = $this->getMock(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService::class, array('serializeAndHashFormFieldArray'));
124 $requestHashService->generateTrustedPropertiesToken($input);
125 }
126
127 /**
128 * @test
129 */
130 public function serializeAndHashFormFieldArrayWorks() {
131 $formFieldArray = array(
132 'bla' => array(
133 'blubb' => 1,
134 'hu' => 1
135 )
136 );
137 $mockHash = '12345';
138
139 $hashService = $this->getMock($this->buildAccessibleProxy(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService::class), array('appendHmac'));
140 $hashService->expects($this->once())->method('appendHmac')->with(serialize($formFieldArray))->will($this->returnValue(serialize($formFieldArray) . $mockHash));
141
142 $requestHashService = $this->getMock($this->buildAccessibleProxy(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService::class), array('dummy'));
143 $requestHashService->_set('hashService', $hashService);
144
145 $expected = serialize($formFieldArray) . $mockHash;
146 $actual = $requestHashService->_call('serializeAndHashFormFieldArray', $formFieldArray);
147 $this->assertEquals($expected, $actual);
148 }
149
150 /**
151 * @test
152 */
153 public function initializePropertyMappingConfigurationDoesNothingIfTrustedPropertiesAreNotSet() {
154 $request = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\Request::class)->setMethods(array('getInternalArgument'))->disableOriginalConstructor()->getMock();
155 $request->expects($this->any())->method('getInternalArgument')->with('__trustedProperties')->will($this->returnValue(NULL));
156 $arguments = new \TYPO3\CMS\Extbase\Mvc\Controller\Arguments();
157
158 $requestHashService = new \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService;
159 $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
160 }
161
162 /**
163 * @test
164 */
165 public function initializePropertyMappingConfigurationReturnsEarlyIfNoTrustedPropertiesAreSet() {
166 $trustedProperties = array(
167 'foo' => 1
168 );
169 $this->initializePropertyMappingConfiguration($trustedProperties);
170 }
171
172 /**
173 * @test
174 */
175 public function initializePropertyMappingConfigurationReturnsEarlyIfArgumentIsUnknown() {
176 $trustedProperties = array(
177 'nonExistingArgument' => 1
178 );
179 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
180 $this->assertFalse($arguments->hasArgument('nonExistingArgument'));
181 }
182
183 /**
184 * @test
185 */
186 public function initializePropertyMappingConfigurationSetsModificationAllowedIfIdentityPropertyIsSet() {
187 $trustedProperties = array(
188 'foo' => array(
189 '__identity' => 1,
190 'nested' => array(
191 '__identity' => 1,
192 )
193 )
194 );
195 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
196 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
197 $this->assertTrue($propertyMappingConfiguration->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
198 $this->assertNull($propertyMappingConfiguration->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
199 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
200
201 $this->assertTrue($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED), 'ConfigurationValue is not CONFIGURATION_MODIFICATION_ALLOWED at line ' . __LINE__);
202 $this->assertNull($propertyMappingConfiguration->forProperty('nested')->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED), 'ConfigurationValue is not NULL at line ' . __LINE__);
203 $this->assertFalse($propertyMappingConfiguration->forProperty('nested')->shouldMap('someProperty'), 'Value is not FALSE at line ' . __LINE__);
204 }
205
206 /**
207 * @test
208 */
209 public function initializePropertyMappingConfigurationSetsCreationAllowedIfIdentityPropertyIsNotSet() {
210 $trustedProperties = array(
211 'foo' => array(
212 'bar' => array()
213 )
214 );
215 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
216 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
217 $this->assertNull($propertyMappingConfiguration->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
218 $this->assertTrue($propertyMappingConfiguration->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
219 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
220
221 $this->assertNull($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_MODIFICATION_ALLOWED));
222 $this->assertTrue($propertyMappingConfiguration->forProperty('bar')->getConfigurationValue(\TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::class, \TYPO3\CMS\Extbase\Property\TypeConverter\PersistentObjectConverter::CONFIGURATION_CREATION_ALLOWED));
223 $this->assertFalse($propertyMappingConfiguration->forProperty('bar')->shouldMap('someProperty'));
224 }
225
226 /**
227 * @test
228 */
229 public function initializePropertyMappingConfigurationSetsAllowedFields() {
230 $trustedProperties = array(
231 'foo' => array(
232 'bar' => 1
233 )
234 );
235 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
236 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
237 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
238 $this->assertTrue($propertyMappingConfiguration->shouldMap('bar'));
239 }
240
241 /**
242 * @test
243 */
244 public function initializePropertyMappingConfigurationSetsAllowedFieldsRecursively() {
245 $trustedProperties = array(
246 'foo' => array(
247 'bar' => array(
248 'foo' => 1
249 )
250 )
251 );
252 $arguments = $this->initializePropertyMappingConfiguration($trustedProperties);
253 $propertyMappingConfiguration = $arguments->getArgument('foo')->getPropertyMappingConfiguration();
254 $this->assertFalse($propertyMappingConfiguration->shouldMap('someProperty'));
255 $this->assertTrue($propertyMappingConfiguration->shouldMap('bar'));
256 $this->assertTrue($propertyMappingConfiguration->forProperty('bar')->shouldMap('foo'));
257 }
258
259 /**
260 * Helper which initializes the property mapping configuration and returns arguments
261 *
262 * @param array $trustedProperties
263 *
264 * @return \TYPO3\CMS\Extbase\Mvc\Controller\Arguments
265 */
266 protected function initializePropertyMappingConfiguration(array $trustedProperties) {
267 $request = $this->getMockBuilder(\TYPO3\CMS\Extbase\Mvc\Request::class)->setMethods(array('getInternalArgument'))->disableOriginalConstructor()->getMock();
268 $request->expects($this->any())->method('getInternalArgument')->with('__trustedProperties')->will($this->returnValue('fooTrustedProperties'));
269
270 $mockHashService = $this->getMock(\TYPO3\CMS\Extbase\Security\Cryptography\HashService::class, array('validateAndStripHmac'));
271 $mockHashService->expects($this->once())->method('validateAndStripHmac')->with('fooTrustedProperties')->will($this->returnValue(serialize($trustedProperties)));
272
273 $requestHashService = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfigurationService::class, array('dummy'));
274 $requestHashService->_set('hashService', $mockHashService);
275
276 $mockObjectManager = $this->getMock(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface::class);
277 $mockArgument = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\Controller\Argument::class, array('getName'), array(), '', FALSE);
278
279 $propertyMappingConfiguration = new \TYPO3\CMS\Extbase\Mvc\Controller\MvcPropertyMappingConfiguration();
280
281 $mockArgument->_set('propertyMappingConfiguration', $propertyMappingConfiguration);
282 $mockArgument->expects($this->any())->method('getName')->will($this->returnValue('foo'));
283 $mockObjectManager->expects($this->once())->method('get')->with(\TYPO3\CMS\Extbase\Mvc\Controller\Argument::class)->will($this->returnValue($mockArgument));
284
285 $arguments = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Mvc\Controller\Arguments::class, array('dummy'));
286 $arguments->_set('objectManager', $mockObjectManager);
287 $arguments->addNewArgument('foo');
288
289 $requestHashService->initializePropertyMappingConfigurationFromRequest($request, $arguments);
290
291 return $arguments;
292 }
293
294 }