Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
140 | class CastableObject |
||
141 | { |
||
142 | public $foo; |
||
143 | |||
144 | public function __toString() |
||
145 | { |
||
146 | return $this->foo; |
||
147 | } |
||
148 | } |
||
149 | |||
150 | class ModelToElasticaAutoTransformerTest extends \PHPUnit_Framework_TestCase |
||
151 | { |
||
152 | public function testTransformerDispatches() |
||
153 | { |
||
154 | $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface') |
||
155 | ->getMock(); |
||
156 | |||
157 | $dispatcher->expects($this->exactly(2)) |
||
158 | ->method('dispatch') |
||
159 | ->withConsecutive( |
||
160 | array( |
||
161 | TransformEvent::PRE_TRANSFORM, |
||
162 | $this->isInstanceOf('FOS\ElasticaBundle\Event\TransformEvent') |
||
163 | ), |
||
164 | array( |
||
165 | TransformEvent::POST_TRANSFORM, |
||
166 | $this->isInstanceOf('FOS\ElasticaBundle\Event\TransformEvent') |
||
167 | ) |
||
168 | ); |
||
169 | |||
170 | $transformer = $this->getTransformer($dispatcher); |
||
171 | $transformer->transform(new POPO(), array()); |
||
172 | } |
||
173 | |||
174 | public function testPropertyPath() |
||
175 | { |
||
176 | $transformer = $this->getTransformer(); |
||
177 | |||
178 | $document = $transformer->transform(new POPO(), array('name' => array('property_path' => false))); |
||
179 | $this->assertInstanceOf('Elastica\Document', $document); |
||
180 | $this->assertFalse($document->has('name')); |
||
181 | |||
182 | $document = $transformer->transform(new POPO(), array('realName' => array('property_path' => 'name'))); |
||
183 | $this->assertInstanceOf('Elastica\Document', $document); |
||
184 | $this->assertTrue($document->has('realName')); |
||
185 | $this->assertEquals('someName', $document->get('realName')); |
||
186 | } |
||
187 | |||
188 | public function testThatCanTransformObject() |
||
189 | { |
||
190 | $transformer = $this->getTransformer(); |
||
191 | $document = $transformer->transform(new POPO(), array('name' => array())); |
||
192 | $data = $document->getData(); |
||
193 | |||
194 | $this->assertInstanceOf('Elastica\Document', $document); |
||
195 | $this->assertEquals(123, $document->getId()); |
||
196 | $this->assertEquals('someName', $data['name']); |
||
197 | } |
||
198 | |||
199 | public function testThatCanTransformObjectWithCorrectTypes() |
||
200 | { |
||
201 | $transformer = $this->getTransformer(); |
||
202 | $document = $transformer->transform( |
||
203 | new POPO(), array( |
||
204 | 'name' => array(), |
||
205 | 'float' => array(), |
||
206 | 'bool' => array(), |
||
207 | 'date' => array(), |
||
208 | 'falseBool' => array(), |
||
209 | ) |
||
210 | ); |
||
211 | $data = $document->getData(); |
||
212 | |||
213 | $this->assertInstanceOf('Elastica\Document', $document); |
||
214 | $this->assertEquals(123, $document->getId()); |
||
215 | $this->assertEquals('someName', $data['name']); |
||
216 | $this->assertEquals(7.2, $data['float']); |
||
217 | $this->assertEquals(true, $data['bool']); |
||
218 | $this->assertEquals(false, $data['falseBool']); |
||
219 | $expectedDate = new \DateTime('1979-05-05'); |
||
220 | $this->assertEquals($expectedDate->format('c'), $data['date']); |
||
221 | } |
||
222 | |||
223 | public function testThatCanTransformObjectWithIteratorValue() |
||
224 | { |
||
225 | $transformer = $this->getTransformer(); |
||
226 | $document = $transformer->transform(new POPO(), array('iterator' => array())); |
||
227 | $data = $document->getData(); |
||
228 | |||
229 | $this->assertEquals(array('value1'), $data['iterator']); |
||
230 | } |
||
231 | |||
232 | public function testThatCanTransformObjectWithArrayValue() |
||
233 | { |
||
234 | $transformer = $this->getTransformer(); |
||
235 | $document = $transformer->transform(new POPO(), array('array' => array())); |
||
236 | $data = $document->getData(); |
||
237 | |||
238 | $this->assertEquals( |
||
239 | array( |
||
240 | 'key1' => 'value1', |
||
241 | 'key2' => 'value2', |
||
242 | ), $data['array'] |
||
243 | ); |
||
244 | } |
||
245 | |||
246 | public function testThatCanTransformObjectWithMultiDimensionalArrayValue() |
||
247 | { |
||
248 | $transformer = $this->getTransformer(); |
||
249 | $document = $transformer->transform(new POPO(), array('multiArray' => array())); |
||
250 | $data = $document->getData(); |
||
251 | |||
252 | $expectedDate = new \DateTime('1978-09-07'); |
||
253 | |||
254 | $this->assertEquals( |
||
255 | array( |
||
256 | 'key1' => 'value1', |
||
257 | 'key2' => array('value2', false, 123, 8.9, $expectedDate->format('c')), |
||
258 | ), $data['multiArray'] |
||
259 | ); |
||
260 | } |
||
261 | |||
262 | public function testThatNullValuesAreNotFilteredOut() |
||
263 | { |
||
264 | $transformer = $this->getTransformer(); |
||
265 | $document = $transformer->transform(new POPO(), array('nullValue' => array())); |
||
266 | $data = $document->getData(); |
||
267 | |||
268 | $this->assertTrue(array_key_exists('nullValue', $data)); |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * @expectedException Symfony\Component\PropertyAccess\Exception\RuntimeException |
||
273 | */ |
||
274 | public function testThatCannotTransformObjectWhenGetterDoesNotExistForPrivateMethod() |
||
275 | { |
||
276 | $transformer = $this->getTransformer(); |
||
277 | $transformer->transform(new POPO(), array('desc' => array())); |
||
278 | } |
||
279 | |||
280 | public function testFileAddedForAttachmentMapping() |
||
281 | { |
||
282 | $transformer = $this->getTransformer(); |
||
283 | $document = $transformer->transform(new POPO(), array('file' => array('type' => 'attachment'))); |
||
284 | $data = $document->getData(); |
||
285 | |||
286 | $this->assertEquals(base64_encode(file_get_contents(__DIR__.'/../fixtures/attachment.odt')), $data['file']); |
||
287 | } |
||
288 | |||
289 | public function testFileContentsAddedForAttachmentMapping() |
||
290 | { |
||
291 | $transformer = $this->getTransformer(); |
||
292 | $document = $transformer->transform(new POPO(), array('fileContents' => array('type' => 'attachment'))); |
||
293 | $data = $document->getData(); |
||
294 | |||
295 | $this->assertEquals( |
||
296 | base64_encode(file_get_contents(__DIR__.'/../fixtures/attachment.odt')), $data['fileContents'] |
||
297 | ); |
||
298 | } |
||
299 | |||
300 | public function testNestedMapping() |
||
301 | { |
||
302 | $transformer = $this->getTransformer(); |
||
303 | $document = $transformer->transform(new POPO(), array( |
||
304 | 'sub' => array( |
||
305 | 'type' => 'nested', |
||
306 | 'properties' => array('foo' => array()), |
||
307 | ), |
||
308 | )); |
||
309 | $data = $document->getData(); |
||
310 | |||
311 | $this->assertTrue(array_key_exists('sub', $data)); |
||
312 | $this->assertInternalType('array', $data['sub']); |
||
313 | $this->assertEquals(array( |
||
314 | array('foo' => 'foo'), |
||
315 | array('foo' => 'bar'), |
||
316 | ), $data['sub']); |
||
317 | } |
||
318 | |||
319 | public function tesObjectMapping() |
||
320 | { |
||
321 | $transformer = $this->getTransformer(); |
||
322 | $document = $transformer->transform(new POPO(), array( |
||
323 | 'sub' => array( |
||
324 | 'type' => 'object', |
||
325 | 'properties' => array('bar'), |
||
326 | ), |
||
327 | )); |
||
328 | $data = $document->getData(); |
||
329 | |||
330 | $this->assertTrue(array_key_exists('sub', $data)); |
||
331 | $this->assertInternalType('array', $data['sub']); |
||
332 | $this->assertEquals(array( |
||
333 | array('bar' => 'foo'), |
||
334 | array('bar' => 'bar'), |
||
335 | ), $data['sub']); |
||
336 | } |
||
337 | |||
338 | public function testObjectDoesNotRequireProperties() |
||
339 | { |
||
340 | $transformer = $this->getTransformer(); |
||
341 | $document = $transformer->transform(new POPO(), array( |
||
342 | 'obj' => array( |
||
343 | 'type' => 'object', |
||
344 | ), |
||
345 | )); |
||
346 | $data = $document->getData(); |
||
347 | |||
348 | $this->assertTrue(array_key_exists('obj', $data)); |
||
349 | $this->assertInternalType('array', $data['obj']); |
||
350 | $this->assertEquals(array( |
||
351 | 'foo' => 'foo', |
||
352 | 'bar' => 'foo', |
||
353 | 'id' => 1, |
||
354 | ), $data['obj']); |
||
355 | } |
||
356 | |||
357 | public function testObjectsMappingOfAtLeastOneAutoMappedObjectAndAtLeastOneManuallyMappedObject() |
||
358 | { |
||
359 | $transformer = $this->getTransformer(); |
||
360 | $document = $transformer->transform( |
||
361 | new POPO(), |
||
362 | array( |
||
363 | 'obj' => array('type' => 'object', 'properties' => array()), |
||
364 | 'nestedObject' => array( |
||
365 | 'type' => 'object', |
||
366 | 'properties' => array( |
||
367 | 'key1sub1' => array( |
||
368 | 'type' => 'string', |
||
369 | 'properties' => array(), |
||
370 | ), |
||
371 | 'key1sub2' => array( |
||
372 | 'type' => 'string', |
||
373 | 'properties' => array(), |
||
374 | ), |
||
375 | ), |
||
376 | ), |
||
377 | ) |
||
378 | ); |
||
379 | $data = $document->getData(); |
||
380 | |||
381 | $this->assertTrue(array_key_exists('obj', $data)); |
||
382 | $this->assertTrue(array_key_exists('nestedObject', $data)); |
||
383 | $this->assertInternalType('array', $data['obj']); |
||
384 | $this->assertInternalType('array', $data['nestedObject']); |
||
385 | $this->assertEquals( |
||
386 | array( |
||
387 | 'foo' => 'foo', |
||
388 | 'bar' => 'foo', |
||
389 | 'id' => 1, |
||
390 | ), |
||
391 | $data['obj'] |
||
392 | ); |
||
393 | $this->assertEquals( |
||
394 | array( |
||
395 | 'key1sub1' => 'value1sub1', |
||
396 | 'key1sub2' => 'value1sub2', |
||
397 | ), |
||
398 | $data['nestedObject'][0] |
||
399 | ); |
||
400 | } |
||
401 | |||
402 | public function testParentMapping() |
||
403 | { |
||
404 | $transformer = $this->getTransformer(); |
||
405 | $document = $transformer->transform(new POPO(), array( |
||
406 | '_parent' => array('type' => 'upper', 'property' => 'upper', 'identifier' => 'id'), |
||
407 | )); |
||
408 | |||
409 | $this->assertEquals("parent", $document->getParent()); |
||
410 | } |
||
411 | |||
412 | public function testParentMappingWithCustomIdentifier() |
||
413 | { |
||
414 | $transformer = $this->getTransformer(); |
||
415 | $document = $transformer->transform(new POPO(), array( |
||
416 | '_parent' => array('type' => 'upper', 'property' => 'upper', 'identifier' => 'name'), |
||
417 | )); |
||
418 | |||
419 | $this->assertEquals("a random name", $document->getParent()); |
||
420 | } |
||
421 | |||
422 | public function testParentMappingWithNullProperty() |
||
423 | { |
||
424 | $transformer = $this->getTransformer(); |
||
425 | $document = $transformer->transform(new POPO(), array( |
||
426 | '_parent' => array('type' => 'upper', 'property' => null, 'identifier' => 'id'), |
||
427 | )); |
||
428 | |||
429 | $this->assertEquals("parent", $document->getParent()); |
||
430 | } |
||
431 | |||
432 | public function testParentMappingWithCustomProperty() |
||
433 | { |
||
434 | $transformer = $this->getTransformer(); |
||
435 | $document = $transformer->transform(new POPO(), array( |
||
436 | '_parent' => array('type' => 'upper', 'property' => 'upperAlias', 'identifier' => 'id'), |
||
437 | )); |
||
438 | |||
439 | $this->assertEquals("parent", $document->getParent()); |
||
440 | } |
||
441 | |||
442 | public function testThatMappedObjectsDontNeedAnIdentifierField() |
||
443 | { |
||
444 | $transformer = $this->getTransformer(); |
||
445 | $document = $transformer->transform(new POPO(), array( |
||
446 | 'objWithoutIdentifier' => array( |
||
447 | 'type' => 'object', |
||
448 | 'properties' => array( |
||
449 | 'foo' => array(), |
||
450 | 'bar' => array() |
||
451 | ) |
||
452 | ), |
||
453 | )); |
||
454 | $data = $document->getData(); |
||
455 | |||
456 | $this->assertTrue(array_key_exists('objWithoutIdentifier', $data)); |
||
457 | $this->assertInternalType('array', $data['objWithoutIdentifier']); |
||
458 | $this->assertEquals(array( |
||
459 | 'foo' => 'foo', |
||
460 | 'bar' => 'foo' |
||
461 | ), $data['objWithoutIdentifier']); |
||
462 | } |
||
463 | |||
464 | public function testThatNestedObjectsDontNeedAnIdentifierField() |
||
465 | { |
||
466 | $transformer = $this->getTransformer(); |
||
467 | $document = $transformer->transform(new POPO(), array( |
||
468 | 'subWithoutIdentifier' => array( |
||
469 | 'type' => 'nested', |
||
470 | 'properties' => array( |
||
471 | 'foo' => array(), |
||
472 | 'bar' => array() |
||
473 | ), |
||
474 | ), |
||
475 | )); |
||
476 | $data = $document->getData(); |
||
477 | |||
478 | $this->assertTrue(array_key_exists('subWithoutIdentifier', $data)); |
||
479 | $this->assertInternalType('array', $data['subWithoutIdentifier']); |
||
480 | $this->assertEquals(array( |
||
481 | array('foo' => 'foo', 'bar' => 'foo'), |
||
482 | array('foo' => 'bar', 'bar' => 'bar'), |
||
483 | ), $data['subWithoutIdentifier']); |
||
484 | } |
||
485 | |||
486 | public function testNestedTransformHandlesSingleObjects() |
||
487 | { |
||
488 | $transformer = $this->getTransformer(); |
||
489 | $document = $transformer->transform(new POPO(), array( |
||
545 |