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 |