109e6f769fa92c3294bf6eeb5c68a2965bc61a3c
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Tests / Unit / Persistence / Generic / Mapper / DataMapperTest.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Tests\Unit\Persistence\Generic\Mapper;
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 DataMapperTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
21
22 /**
23 * @test
24 */
25 public function mapMapsArrayToObjectByCallingmapToObject() {
26 $rows = array(array('uid' => '1234'));
27 $object = new \stdClass();
28 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('mapSingleRow', 'getTargetType'));
29 $dataMapper->expects($this->any())->method('getTargetType')->will($this->returnArgument(1));
30 $dataMapFactory = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapFactory');
31 $dataMapper->_set('dataMapFactory', $dataMapFactory);
32 $dataMapper->expects($this->once())->method('mapSingleRow')->with($rows[0])->will($this->returnValue($object));
33 $dataMapper->map(get_class($object), $rows);
34 }
35
36 /**
37 * @test
38 */
39 public function mapSingleRowReturnsObjectFromIdentityMapIfAvailable() {
40 $row = array('uid' => '1234');
41 $object = new \stdClass();
42 $identityMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\IdentityMap');
43 $identityMap->expects($this->once())->method('hasIdentifier')->with('1234')->will($this->returnValue(TRUE));
44 $identityMap->expects($this->once())->method('getObjectByIdentifier')->with('1234')->will($this->returnValue($object));
45 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('dummy'));
46 $dataMapper->_set('identityMap', $identityMap);
47 $dataMapper->_call('mapSingleRow', get_class($object), $row);
48 }
49
50 /**
51 * @test
52 */
53 public function thawPropertiesSetsPropertyValues() {
54 $className = 'Class' . md5(uniqid(mt_rand(), TRUE));
55 $classNameWithNS = __NAMESPACE__ . '\\' . $className;
56 eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { public $firstProperty; public $secondProperty; public $thirdProperty; public $fourthProperty; }');
57 $object = new $classNameWithNS();
58 $row = array(
59 'uid' => '1234',
60 'firstProperty' => 'firstValue',
61 'secondProperty' => 1234,
62 'thirdProperty' => 1.234,
63 'fourthProperty' => FALSE
64 );
65 $columnMaps = array(
66 'uid' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('uid', 'uid'),
67 'pid' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('pid', 'pid'),
68 'firstProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('firstProperty', 'firstProperty'),
69 'secondProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('secondProperty', 'secondProperty'),
70 'thirdProperty' => new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('thirdProperty', 'thirdProperty')
71 );
72 $dataMap = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('dummy'), array($className, $className));
73 $dataMap->_set('columnMaps', $columnMaps);
74 $dataMaps = array(
75 $classNameWithNS => $dataMap
76 );
77 /** @var \TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Extbase\Reflection\ClassSchema $classSchema */
78 $classSchema = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
79 $classSchema->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
80 $classSchema->addProperty('pid', 'integer');
81 $classSchema->addProperty('uid', 'integer');
82 $classSchema->addProperty('firstProperty', 'string');
83 $classSchema->addProperty('secondProperty', 'integer');
84 $classSchema->addProperty('thirdProperty', 'float');
85 $classSchema->addProperty('fourthProperty', 'boolean');
86 $mockReflectionService = $this->getMock('TYPO3\\CMS\\Extbase\\Reflection\\ReflectionService', array('getClassSchema'));
87 $mockReflectionService->expects($this->any())->method('getClassSchema')->will($this->returnValue($classSchema));
88 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('dummy'));
89 $dataMapper->_set('dataMaps', $dataMaps);
90 $dataMapper->_set('reflectionService', $mockReflectionService);
91 $dataMapper->_call('thawProperties', $object, $row);
92 $this->assertAttributeEquals('firstValue', 'firstProperty', $object);
93 $this->assertAttributeEquals(1234, 'secondProperty', $object);
94 $this->assertAttributeEquals(1.234, 'thirdProperty', $object);
95 $this->assertAttributeEquals(FALSE, 'fourthProperty', $object);
96 }
97
98 /**
99 * Test if fetchRelatedEager method returns NULL when $fieldValue = '' and relation type == RELATION_HAS_ONE
100 *
101 * @test
102 */
103 public function fetchRelatedEagerReturnsNullForEmptyRelationHasOne() {
104 $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
105 $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
106 $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
107 $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
108 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
109 $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
110 $result = $dataMapper->_call('fetchRelatedEager', $this->getMock('TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity'), 'SomeName', '');
111 $this->assertEquals(NULL, $result);
112 }
113
114 /**
115 * Test if fetchRelatedEager method returns empty array when $fieldValue = '' and relation type != RELATION_HAS_ONE
116 *
117 * @test
118 */
119 public function fetchRelatedEagerReturnsEmptyArrayForEmptyRelationNotHasOne() {
120 $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
121 $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_BELONGS_TO_MANY);
122 $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
123 $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
124 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap'));
125 $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
126 $result = $dataMapper->_call('fetchRelatedEager', $this->getMock('TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity'), 'SomeName', '');
127 $this->assertEquals(array(), $result);
128 }
129
130 /**
131 * Test if fetchRelatedEager method returns NULL when $fieldValue = ''
132 * and relation type == RELATION_HAS_ONE without calling fetchRelated
133 *
134 * @test
135 */
136 public function mapObjectToClassPropertyReturnsNullForEmptyRelationHasOne() {
137 $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
138 $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
139 $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
140 $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
141 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap', 'fetchRelated'));
142 $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
143 $dataMapper->expects($this->never())->method('fetchRelated');
144 $result = $dataMapper->_call('mapObjectToClassProperty', $this->getMock('TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity'), 'SomeName', '');
145 $this->assertEquals(NULL, $result);
146 }
147
148 /**
149 * Test if mapObjectToClassProperty method returns objects
150 * that are already registered in the persistence session
151 * without query it from the persistence layer
152 *
153 * @test
154 */
155 public function mapObjectToClassPropertyReturnsExistingObjectWithoutCallingFetchRelated() {
156 $columnMap = new \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap('columnName', 'propertyName');
157 $columnMap->setTypeOfRelation(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\ColumnMap::RELATION_HAS_ONE);
158 $dataMap = $this->getMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMap', array('getColumnMap'), array(), '', FALSE);
159
160 $className = 'Class1' . md5(uniqid(mt_rand(), TRUE));
161 $classNameWithNS = __NAMESPACE__ . '\\' . $className;
162 eval('namespace ' . __NAMESPACE__ . '; class ' . $className . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { public $relationProperty; }');
163 $object = new $classNameWithNS();
164 $classSchema1 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($classNameWithNS));
165 $classSchema1->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
166
167 $className2 = 'Class2' . md5(uniqid(mt_rand(), TRUE));
168 $className2WithNS = __NAMESPACE__ . '\\' . $className2;
169 eval('namespace ' . __NAMESPACE__ . '; class ' . $className2 . ' extends \\TYPO3\\CMS\\Extbase\\DomainObject\\AbstractEntity { }');
170 $child = new $className2WithNS();
171 $classSchema2 = $this->getAccessibleMock('TYPO3\CMS\Extbase\Reflection\ClassSchema', array('dummy'), array($className2WithNS));
172 $classSchema2->_set('typeHandlingService', new \TYPO3\CMS\Extbase\Service\TypeHandlingService());
173
174 $classSchema1->addProperty('relationProperty', $className2WithNS);
175 $identifier = 1;
176
177 $session = new \TYPO3\CMS\Extbase\Persistence\Generic\Session();
178 $session->registerObject($child, $identifier);
179
180 $mockReflectionService = $this->getMock('\TYPO3\CMS\Extbase\Reflection\ReflectionService', array('getClassSchema'), array(), '', FALSE);
181 $mockReflectionService->expects($this->any())->method('getClassSchema')->will($this->returnValue($classSchema1));
182
183 $dataMap->expects($this->any())->method('getColumnMap')->will($this->returnValue($columnMap));
184 $dataMapper = $this->getAccessibleMock('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper', array('getDataMap', 'getNonEmptyRelationValue'));
185 $dataMapper->_set('reflectionService', $mockReflectionService);
186 $dataMapper->_set('persistenceSession', $session);
187 $dataMapper->expects($this->any())->method('getDataMap')->will($this->returnValue($dataMap));
188 $dataMapper->expects($this->never())->method('getNonEmptyRelationValue');
189 $result = $dataMapper->_call('mapObjectToClassProperty', $object, 'relationProperty', $identifier);
190 $this->assertEquals($child, $result);
191 }
192
193 /**
194 * Data provider for date checks. Date will be stored based on UTC in
195 * the database. That's why it's not possible to check for explicit date
196 * strings but using the date('c') conversion instead, which considers the
197 * current local timezone setting.
198 *
199 * @return array
200 */
201 public function mapDateTimeHandlesDifferentFieldEvaluationsDataProvider() {
202 return array(
203 'nothing' => array(NULL, NULL, NULL),
204 'timestamp' => array(1, NULL, date('c', 1)),
205 'empty date' => array('0000-00-00', 'date', NULL),
206 'valid date' => array('2013-01-01', 'date', date('c', strtotime('2013-01-01T00:00:00+00:00'))),
207 'empty datetime' => array('0000-00-00 00:00:00', 'datetime', NULL),
208 'valid datetime' => array('2013-01-01 01:02:03', 'datetime', date('c', strtotime('2013-01-01T01:02:03+00:00'))),
209 );
210 }
211
212 /**
213 * @param NULL|string|integer $value
214 * @param NULL|string $storageFormat
215 * @param NULL|string $expectedValue
216 * @test
217 * @dataProvider mapDateTimeHandlesDifferentFieldEvaluationsDataProvider
218 */
219 public function mapDateTimeHandlesDifferentFieldEvaluations($value, $storageFormat, $expectedValue) {
220 $accessibleClassName = $this->buildAccessibleProxy('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Mapper\\DataMapper');
221 $accessibleDataMapFactory = new $accessibleClassName();
222
223 /** @var $dateTime NULL|\DateTime */
224 $dateTime = $accessibleDataMapFactory->_callRef('mapDateTime', $value, $storageFormat);
225
226 if ($expectedValue === NULL) {
227 $this->assertNull($dateTime);
228 } else {
229 $this->assertEquals($expectedValue, $dateTime->format('c'));
230 }
231 }
232 }