TYPO3 CMS  TYPO3_8-7
DataMapperTest.php
Go to the documentation of this file.
1 <?php
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 
22 
26 class DataMapperTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
27 {
31  public function mapMapsArrayToObjectByCallingmapToObject()
32  {
33  $rows = [['uid' => '1234']];
34  $object = new \stdClass();
36  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['mapSingleRow', 'getTargetType']);
37  $dataMapper->expects($this->any())->method('getTargetType')->will($this->returnArgument(1));
38  $dataMapFactory = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapFactory::class);
39  $dataMapper->_set('dataMapFactory', $dataMapFactory);
40  $dataMapper->expects($this->once())->method('mapSingleRow')->with($rows[0])->will($this->returnValue($object));
41  $dataMapper->map(get_class($object), $rows);
42  }
43 
48  {
49  $row = ['uid' => '1234'];
50  $object = new \stdClass();
51  $persistenceSession = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\Session::class);
52  $persistenceSession->expects($this->once())->method('hasIdentifier')->with('1234')->will($this->returnValue(true));
53  $persistenceSession->expects($this->once())->method('getObjectByIdentifier')->with('1234')->will($this->returnValue($object));
54  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['dummy']);
55  $dataMapper->_set('persistenceSession', $persistenceSession);
56  $dataMapper->_call('mapSingleRow', get_class($object), $row);
57  }
58 
62  public function thawPropertiesSetsPropertyValues()
63  {
64  $className = $this->getUniqueId('Class');
65  $classNameWithNS = __NAMESPACE__ . '\\' . $className;
66  eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' {
67  public $firstProperty; public $secondProperty; public $thirdProperty; public $fourthProperty;
68  }'
69  );
70  $object = new $classNameWithNS();
71  $row = [
72  'uid' => '1234',
73  'firstProperty' => 'firstValue',
74  'secondProperty' => 1234,
75  'thirdProperty' => 1.234,
76  'fourthProperty' => false
77  ];
78  $columnMaps = [
79  'uid' => new ColumnMap('uid', 'uid'),
80  'pid' => new ColumnMap('pid', 'pid'),
81  'firstProperty' => new ColumnMap('firstProperty', 'firstProperty'),
82  'secondProperty' => new ColumnMap('secondProperty', 'secondProperty'),
83  'thirdProperty' => new ColumnMap('thirdProperty', 'thirdProperty')
84  ];
85  $dataMap = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class, ['dummy'], [$className, $className]);
86  $dataMap->_set('columnMaps', $columnMaps);
87  $dataMaps = [
88  $classNameWithNS => $dataMap
89  ];
91  $classSchema = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], [$classNameWithNS]);
92  $classSchema->addProperty('pid', 'integer');
93  $classSchema->addProperty('uid', 'integer');
94  $classSchema->addProperty('firstProperty', 'string');
95  $classSchema->addProperty('secondProperty', 'integer');
96  $classSchema->addProperty('thirdProperty', 'float');
97  $classSchema->addProperty('fourthProperty', 'boolean');
98  $mockReflectionService = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class)
99  ->setMethods(['getClassSchema'])
100  ->getMock();
101  $mockReflectionService->expects($this->any())->method('getClassSchema')->will($this->returnValue($classSchema));
102  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['dummy']);
103  $dataMapper->_set('dataMaps', $dataMaps);
104  $dataMapper->_set('reflectionService', $mockReflectionService);
105  $dataMapper->_call('thawProperties', $object, $row);
106  $this->assertAttributeEquals('firstValue', 'firstProperty', $object);
107  $this->assertAttributeEquals(1234, 'secondProperty', $object);
108  $this->assertAttributeEquals(1.234, 'thirdProperty', $object);
109  $this->assertAttributeEquals(false, 'fourthProperty', $object);
110  }
111 
118  {
119  $columnMap = new ColumnMap('columnName', 'propertyName');
120  $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
121  $dataMap = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class)
122  ->setMethods(['getColumnMap'])
123  ->disableOriginalConstructor()
124  ->getMock();
125  $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
126  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['getDataMap']);
127  $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
128  $result = $dataMapper->_call('fetchRelatedEager', $this->createMock(\TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class), 'SomeName', '');
129  $this->assertEquals(null, $result);
130  }
131 
138  {
139  $columnMap = new ColumnMap('columnName', 'propertyName');
140  $columnMap->setTypeOfRelation(ColumnMap::RELATION_BELONGS_TO_MANY);
141  $dataMap = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class)
142  ->setMethods(['getColumnMap'])
143  ->disableOriginalConstructor()
144  ->getMock();
145  $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
146  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['getDataMap']);
147  $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
148  $result = $dataMapper->_call('fetchRelatedEager', $this->createMock(\TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class), 'SomeName', '');
149  $this->assertEquals([], $result);
150  }
151 
159  {
160  $columnMap = new ColumnMap('columnName', 'propertyName');
161  $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
162  $dataMap = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class)
163  ->setMethods(['getColumnMap'])
164  ->disableOriginalConstructor()
165  ->getMock();
166  $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
167  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['getDataMap', 'fetchRelated']);
168  $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
169  $dataMapper->expects($this->never())->method('fetchRelated');
170  $result = $dataMapper->_call('mapObjectToClassProperty', $this->createMock(\TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class), 'SomeName', '');
171  $this->assertEquals(null, $result);
172  }
173 
181  public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated()
182  {
183  $columnMap = new ColumnMap('columnName', 'propertyName');
184  $columnMap->setTypeOfRelation(ColumnMap::RELATION_HAS_ONE);
185  $dataMap = $this->getMockBuilder(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMap::class)
186  ->setMethods(['getColumnMap'])
187  ->disableOriginalConstructor()
188  ->getMock();
189 
190  $className = $this->getUniqueId('Class1');
191  $classNameWithNS = __NAMESPACE__ . '\\' . $className;
192  eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { public $relationProperty; }');
193  $object = new $classNameWithNS();
194 
195  $className2 = $this->getUniqueId('Class2');
196  $className2WithNS = __NAMESPACE__ . '\\' . $className2;
197  eval('namespace ' . __NAMESPACE__ . '; class ' . $className2 . ' extends \\' . \TYPO3\CMS\Extbase\DomainObject\AbstractEntity::class . ' { }');
198  $child = new $className2WithNS();
199 
201  $classSchema1 = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Reflection\ClassSchema::class, ['dummy'], [$classNameWithNS]);
202  $classSchema1->addProperty('relationProperty', $className2WithNS);
203  $identifier = 1;
204 
205  $session = new \TYPO3\CMS\Extbase\Persistence\Generic\Session();
206  $session->registerObject($child, $identifier);
207 
208  $mockReflectionService = $this->getMockBuilder(\TYPO3\CMS\Extbase\Reflection\ReflectionService::class)
209  ->setMethods(['getClassSchema'])
210  ->disableOriginalConstructor()
211  ->getMock();
212  $mockReflectionService->expects($this->any())->method('getClassSchema')->will($this->returnValue($classSchema1));
213 
214  $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
215  $dataMapper = $this->getAccessibleMock(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class, ['getDataMap', 'getNonEmptyRelationValue']);
216  $dataMapper->_set('reflectionService', $mockReflectionService);
217  $dataMapper->_set('persistenceSession', $session);
218  $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
219  $dataMapper->expects($this->never())->method('getNonEmptyRelationValue');
220  $result = $dataMapper->_call('mapObjectToClassProperty', $object, 'relationProperty', $identifier);
221  $this->assertEquals($child, $result);
222  }
223 
233  {
234  return [
235  'nothing' => [null, null, null],
236  'timestamp' => [1, null, date('c', 1)],
237  'empty date' => ['0000-00-00', 'date', null],
238  'valid date' => ['2013-01-01', 'date', date('c', strtotime('2013-01-01T00:00:00+00:00'))],
239  'empty datetime' => ['0000-00-00 00:00:00', 'datetime', null],
240  'valid datetime' => ['2013-01-01 01:02:03', 'datetime', date('c', strtotime('2013-01-01T01:02:03+00:00'))],
241  ];
242  }
243 
251  public function mapDateTimeHandlesDifferentFieldEvaluations($value, $storageFormat, $expectedValue)
252  {
253  $accessibleClassName = $this->buildAccessibleProxy(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
254 
256  $accessibleDataMapFactory = new $accessibleClassName();
257 
259  $dateTime = $accessibleDataMapFactory->_callRef('mapDateTime', $value, $storageFormat);
260 
261  if ($expectedValue === null) {
262  $this->assertNull($dateTime);
263  } else {
264  $this->assertEquals($expectedValue, $dateTime->format('c'));
265  }
266  }
267 
271  public function mapDateTimeHandlesSubclassesOfDateTime()
272  {
273  $accessibleClassName = $this->buildAccessibleProxy(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
274 
276  $accessibleDataMapFactory = new $accessibleClassName();
277  $targetType = 'TYPO3\CMS\Extbase\Tests\Unit\Persistence\Fixture\Model\CustomDateTime';
278  $date = '2013-01-01 01:02:03';
279  $storageFormat = 'datetime';
280 
282  $dateTime = $accessibleDataMapFactory->_callRef('mapDateTime', $date, $storageFormat, $targetType);
283 
284  $this->assertInstanceOf($targetType, $dateTime);
285  }
286 
291  {
292  $subject = new DataMapper();
293  $columnMap = new ColumnMap('column_name', 'propertyName');
294  $columnMap->setDateTimeStorageFormat('datetime');
295  $datetimeAsString = '2013-04-15 09:30:00';
296  $input = new \DateTime($datetimeAsString, new \DateTimeZone('UTC'));
297  $this->assertEquals('2013-04-15 09:30:00', $subject->getPlainValue($input, $columnMap));
298  $columnMap->setDateTimeStorageFormat('date');
299  $this->assertEquals('2013-04-15', $subject->getPlainValue($input, $columnMap));
300  }
301 
306  public function getPlainValueReturnsExpectedValues($expectedValue, $input)
307  {
308  $dataMapper = new DataMapper();
309  $this->assertSame($expectedValue, $dataMapper->getPlainValue($input));
310  }
311 
316  {
317  $traversableDomainObject = $this->prophesize()
318  ->willImplement(\Iterator::class)
319  ->willImplement(DomainObjectInterface::class);
320  $traversableDomainObject->getUid()->willReturn(1);
321 
322  return [
323  'datetime to timestamp' => ['1365866253', new \DateTime('@1365866253')],
324  'boolean true to 1' => [1, true],
325  'boolean false to 0' => [0, false],
326  'NULL is handled as string' => ['NULL', null],
327  'string value is returned unchanged' => ['RANDOM string', 'RANDOM string'],
328  'array is flattened' => ['a,b,c', ['a', 'b', 'c']],
329  'deep array is flattened' => ['a,b,c', [['a', 'b'], 'c']],
330  'traversable domain object to identifier' => [1, $traversableDomainObject->reveal()],
331  'integer value is returned unchanged' => [1234, 1234],
332  'float is converted to string' => ['1234.56', 1234.56],
333  ];
334  }
335 
340  {
341  $this->expectException(UnexpectedTypeException::class);
342  $this->expectExceptionCode(1274799934);
343  $dataMapper = new DataMapper();
344  $input = $this->createMock(\TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy::class);
345  $input->expects($this->once())->method('_loadRealInstance')->will($this->returnValue($dataMapper));
346  $dataMapper->getPlainValue($input);
347  }
348 
353  {
354  $dataMapper = new DataMapper();
355  $input = $this->createMock(\TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface::class);
356 
357  $input->expects($this->once())->method('getUid')->will($this->returnValue(23));
358  $this->assertSame(23, $dataMapper->getPlainValue($input));
359  }
360 }