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:
Complex classes like FOSElasticaExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FOSElasticaExtension, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | class FOSElasticaExtension extends Extension |
||
23 | { |
||
24 | /** |
||
25 | * Definition of elastica clients as configured by this extension. |
||
26 | * |
||
27 | * @var array |
||
28 | */ |
||
29 | private $clients = []; |
||
30 | |||
31 | /** |
||
32 | * An array of indexes as configured by the extension. |
||
33 | * |
||
34 | * @var array |
||
35 | */ |
||
36 | private $indexConfigs = []; |
||
37 | |||
38 | /** |
||
39 | * If we've encountered a type mapped to a specific persistence driver, it will be loaded |
||
40 | * here. |
||
41 | * |
||
42 | * @var array |
||
43 | */ |
||
44 | private $loadedDrivers = []; |
||
45 | |||
46 | 12 | public function load(array $configs, ContainerBuilder $container) |
|
47 | { |
||
48 | 12 | $configuration = $this->getConfiguration($configs, $container); |
|
49 | 12 | $config = $this->processConfiguration($configuration, $configs); |
|
50 | |||
51 | 12 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); |
|
52 | |||
53 | 12 | if (empty($config['clients']) || empty($config['indexes'])) { |
|
54 | // No Clients or indexes are defined |
||
55 | return; |
||
56 | } |
||
57 | |||
58 | 12 | foreach (['config', 'index', 'persister', 'provider', 'source', 'transformer', 'event_listener'] as $basename) { |
|
59 | 12 | $loader->load(sprintf('%s.xml', $basename)); |
|
60 | } |
||
61 | |||
62 | 12 | if (empty($config['default_client'])) { |
|
63 | 12 | $keys = array_keys($config['clients']); |
|
64 | 12 | $config['default_client'] = reset($keys); |
|
65 | } |
||
66 | |||
67 | 12 | if (empty($config['default_index'])) { |
|
68 | 12 | $keys = array_keys($config['indexes']); |
|
69 | 12 | $config['default_index'] = reset($keys); |
|
70 | } |
||
71 | |||
72 | 12 | if (isset($config['serializer'])) { |
|
73 | 1 | $loader->load('serializer.xml'); |
|
74 | |||
75 | 1 | $this->loadSerializer($config['serializer'], $container); |
|
76 | } |
||
77 | |||
78 | 12 | $this->loadClients($config['clients'], $container); |
|
79 | 12 | $container->setAlias('fos_elastica.client', sprintf('fos_elastica.client.%s', $config['default_client'])); |
|
80 | |||
81 | 12 | $this->loadIndexes($config['indexes'], $container); |
|
82 | 12 | $container->setAlias('fos_elastica.index', sprintf('fos_elastica.index.%s', $config['default_index'])); |
|
83 | 12 | $container->setParameter('fos_elastica.default_index', $config['default_index']); |
|
84 | |||
85 | 12 | $container->getDefinition('fos_elastica.config_source.container')->replaceArgument(0, $this->indexConfigs); |
|
86 | |||
87 | 12 | $this->loadIndexManager($container); |
|
88 | |||
89 | 12 | $this->createDefaultManagerAlias($config['default_manager'], $container); |
|
90 | 12 | } |
|
91 | |||
92 | /** |
||
93 | * @param array $config |
||
94 | * @param ContainerBuilder $container |
||
95 | * |
||
96 | * @return Configuration |
||
97 | */ |
||
98 | 12 | public function getConfiguration(array $config, ContainerBuilder $container) |
|
102 | |||
103 | /** |
||
104 | * Loads the configured clients. |
||
105 | * |
||
106 | * @param array $clients An array of clients configurations |
||
107 | * @param ContainerBuilder $container A ContainerBuilder instance |
||
108 | * |
||
109 | * @return array |
||
110 | */ |
||
111 | 12 | private function loadClients(array $clients, ContainerBuilder $container) |
|
134 | |||
135 | /** |
||
136 | * Loads the configured indexes. |
||
137 | * |
||
138 | * @param array $indexes An array of indexes configurations |
||
139 | * @param ContainerBuilder $container A ContainerBuilder instance |
||
140 | * |
||
141 | * @throws \InvalidArgumentException |
||
142 | * |
||
143 | * @return array |
||
144 | */ |
||
145 | 12 | private function loadIndexes(array $indexes, ContainerBuilder $container) |
|
188 | |||
189 | /** |
||
190 | * Loads the configured index finders. |
||
191 | * |
||
192 | * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container |
||
193 | * @param string $name The index name |
||
194 | * @param Reference $index Reference to the related index |
||
195 | * |
||
196 | * @return string |
||
197 | */ |
||
198 | private function loadIndexFinder(ContainerBuilder $container, $name, Reference $index) |
||
214 | |||
215 | /** |
||
216 | * Loads the configured types. |
||
217 | * |
||
218 | * @param array $types |
||
219 | * @param ContainerBuilder $container |
||
220 | * @param array $indexConfig |
||
221 | * @param array $indexableCallbacks |
||
222 | */ |
||
223 | 12 | private function loadTypes(array $types, ContainerBuilder $container, array $indexConfig, array &$indexableCallbacks) |
|
308 | |||
309 | /** |
||
310 | * Loads the optional provider and finder for a type. |
||
311 | * |
||
312 | * @param array $typeConfig |
||
313 | * @param ContainerBuilder $container |
||
314 | * @param Reference $typeRef |
||
315 | * @param string $indexName |
||
316 | * @param string $typeName |
||
317 | */ |
||
318 | 11 | private function loadTypePersistenceIntegration(array $typeConfig, ContainerBuilder $container, Reference $typeRef, $indexName, $typeName) |
|
338 | |||
339 | /** |
||
340 | * Creates and loads an ElasticaToModelTransformer. |
||
341 | * |
||
342 | * @param array $typeConfig |
||
343 | * @param ContainerBuilder $container |
||
344 | * @param string $indexName |
||
345 | * @param string $typeName |
||
346 | * |
||
347 | * @return string |
||
348 | */ |
||
349 | 11 | private function loadElasticaToModelTransformer(array $typeConfig, ContainerBuilder $container, $indexName, $typeName) |
|
374 | |||
375 | /** |
||
376 | * Creates and loads a ModelToElasticaTransformer for an index/type. |
||
377 | * |
||
378 | * @param array $typeConfig |
||
379 | * @param ContainerBuilder $container |
||
380 | * @param string $indexName |
||
381 | * @param string $typeName |
||
382 | * |
||
383 | * @return string |
||
384 | */ |
||
385 | 11 | private function loadModelToElasticaTransformer(array $typeConfig, ContainerBuilder $container, $indexName, $typeName) |
|
404 | |||
405 | /** |
||
406 | * Creates and loads an object persister for a type. |
||
407 | * |
||
408 | * @param array $typeConfig |
||
409 | * @param Reference $typeRef |
||
410 | * @param ContainerBuilder $container |
||
411 | * @param string $indexName |
||
412 | * @param string $typeName |
||
413 | * @param string $transformerId |
||
414 | * |
||
415 | * @return string |
||
416 | */ |
||
417 | 11 | private function loadObjectPersister(array $typeConfig, Reference $typeRef, ContainerBuilder $container, $indexName, $typeName, $transformerId) |
|
455 | |||
456 | /** |
||
457 | * Loads a pager provider for a type. |
||
458 | * |
||
459 | * @param array $typeConfig |
||
460 | * @param ContainerBuilder $container |
||
461 | * @param string $indexName |
||
462 | * @param string $typeName |
||
463 | * |
||
464 | * @return string |
||
465 | */ |
||
466 | 11 | private function loadTypePagerProvider(array $typeConfig, ContainerBuilder $container, $indexName, $typeName) |
|
467 | { |
||
468 | 11 | if (isset($typeConfig['provider']['service'])) { |
|
469 | return $typeConfig['provider']['service']; |
||
470 | } |
||
471 | |||
472 | 11 | $baseConfig = $typeConfig['provider']; |
|
473 | 11 | unset($baseConfig['service']); |
|
474 | |||
475 | 11 | $driver = $typeConfig['driver']; |
|
476 | |||
477 | switch ($driver) { |
||
478 | 11 | case 'orm': |
|
479 | 6 | $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver); |
|
480 | 6 | $providerDef->replaceArgument(2, $typeConfig['model']); |
|
481 | 6 | $providerDef->replaceArgument(3, $baseConfig); |
|
482 | |||
483 | 6 | break; |
|
484 | 5 | View Code Duplication | case 'mongodb': |
485 | $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver); |
||
486 | $providerDef->replaceArgument(2, $typeConfig['model']); |
||
487 | $providerDef->replaceArgument(3, $baseConfig); |
||
488 | |||
489 | break; |
||
490 | 5 | View Code Duplication | case 'phpcr': |
491 | 1 | $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver); |
|
492 | 1 | $providerDef->replaceArgument(2, $typeConfig['model']); |
|
493 | 1 | $providerDef->replaceArgument(3, $baseConfig); |
|
494 | |||
495 | 1 | break; |
|
496 | 4 | View Code Duplication | case 'propel': |
497 | 4 | $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver); |
|
498 | 4 | $providerDef->replaceArgument(0, $typeConfig['model']); |
|
499 | 4 | $providerDef->replaceArgument(1, $baseConfig); |
|
500 | |||
501 | 4 | break; |
|
502 | default: |
||
503 | throw new \LogicException(sprintf('The pager provider for driver "%s" does not exist.', $driver)); |
||
504 | } |
||
505 | |||
506 | /* Note: provider services may conflict with "prototype.driver", if the |
||
507 | * index and type names were "prototype" and a driver, respectively. |
||
508 | */ |
||
509 | 11 | $providerId = sprintf('fos_elastica.pager_provider.%s.%s', $indexName, $typeName); |
|
510 | 11 | $providerDef->addTag('fos_elastica.pager_provider', ['index' => $indexName, 'type' => $typeName]); |
|
511 | |||
512 | 11 | $container->setDefinition($providerId, $providerDef); |
|
513 | |||
514 | 11 | return $providerId; |
|
515 | } |
||
516 | |||
517 | /** |
||
518 | * Loads doctrine listeners to handle indexing of new or updated objects. |
||
519 | * |
||
520 | * @param array $typeConfig |
||
521 | * @param ContainerBuilder $container |
||
522 | * @param string $objectPersisterId |
||
523 | * @param string $indexName |
||
524 | * @param string $typeName |
||
525 | * |
||
526 | * @return string |
||
527 | */ |
||
528 | 11 | private function loadTypeListener(array $typeConfig, ContainerBuilder $container, $objectPersisterId, $indexName, $typeName) |
|
529 | { |
||
530 | 11 | if (isset($typeConfig['listener']['service'])) { |
|
531 | return $typeConfig['listener']['service']; |
||
532 | } |
||
533 | |||
534 | /* Note: listener services may conflict with "prototype.driver", if the |
||
535 | * index and type names were "prototype" and a driver, respectively. |
||
536 | */ |
||
537 | 11 | $abstractListenerId = sprintf('fos_elastica.listener.prototype.%s', $typeConfig['driver']); |
|
538 | 11 | $listenerId = sprintf('fos_elastica.listener.%s.%s', $indexName, $typeName); |
|
539 | 11 | $listenerDef = new DefinitionDecorator($abstractListenerId); |
|
540 | 11 | $listenerDef->replaceArgument(0, new Reference($objectPersisterId)); |
|
541 | 11 | $listenerDef->replaceArgument(3, $typeConfig['listener']['logger'] ? |
|
542 | new Reference($typeConfig['listener']['logger']) : |
||
543 | 11 | null |
|
544 | ); |
||
545 | $listenerConfig = [ |
||
546 | 11 | 'identifier' => $typeConfig['identifier'], |
|
547 | 11 | 'indexName' => $indexName, |
|
548 | 11 | 'typeName' => $typeName, |
|
549 | ]; |
||
550 | |||
551 | 11 | $tagName = null; |
|
552 | 11 | switch ($typeConfig['driver']) { |
|
553 | 11 | case 'orm': |
|
554 | 6 | $tagName = 'doctrine.event_listener'; |
|
555 | 6 | break; |
|
556 | 5 | case 'phpcr': |
|
557 | 1 | $tagName = 'doctrine_phpcr.event_listener'; |
|
558 | 1 | break; |
|
559 | 4 | case 'mongodb': |
|
560 | $tagName = 'doctrine_mongodb.odm.event_listener'; |
||
561 | break; |
||
562 | } |
||
563 | |||
564 | 11 | if ($typeConfig['listener']['defer']) { |
|
565 | $listenerDef->setPublic(true); |
||
566 | $listenerDef->addTag( |
||
567 | 'kernel.event_listener', |
||
568 | ['event' => 'kernel.terminate', 'method' => 'onTerminate'] |
||
569 | ); |
||
570 | $listenerDef->addTag( |
||
571 | 'kernel.event_listener', |
||
572 | ['event' => 'console.terminate', 'method' => 'onTerminate'] |
||
573 | ); |
||
574 | $listenerConfig['defer'] = true; |
||
575 | } |
||
576 | |||
577 | 11 | $listenerDef->replaceArgument(2, $listenerConfig); |
|
578 | |||
579 | 11 | if (null !== $tagName) { |
|
580 | 7 | foreach ($this->getDoctrineEvents($typeConfig) as $event) { |
|
581 | 7 | $listenerDef->addTag($tagName, ['event' => $event]); |
|
582 | } |
||
583 | } |
||
584 | |||
585 | 11 | $container->setDefinition($listenerId, $listenerDef); |
|
586 | |||
587 | 11 | return $listenerId; |
|
588 | } |
||
589 | |||
590 | /** |
||
591 | * Map Elastica to Doctrine events for the current driver. |
||
592 | */ |
||
593 | 7 | private function getDoctrineEvents(array $typeConfig) |
|
594 | { |
||
595 | 7 | switch ($typeConfig['driver']) { |
|
596 | 7 | case 'orm': |
|
597 | 6 | $eventsClass = '\Doctrine\ORM\Events'; |
|
598 | 6 | break; |
|
599 | 1 | case 'phpcr': |
|
600 | 1 | $eventsClass = '\Doctrine\ODM\PHPCR\Event'; |
|
601 | 1 | break; |
|
602 | case 'mongodb': |
||
603 | $eventsClass = '\Doctrine\ODM\MongoDB\Events'; |
||
604 | break; |
||
605 | default: |
||
606 | throw new \InvalidArgumentException(sprintf('Cannot determine events for driver "%s"', $typeConfig['driver'])); |
||
607 | } |
||
608 | |||
609 | 7 | $events = []; |
|
610 | $eventMapping = [ |
||
611 | 7 | 'insert' => [constant($eventsClass.'::postPersist')], |
|
612 | 7 | 'update' => [constant($eventsClass.'::postUpdate')], |
|
613 | 7 | 'delete' => [constant($eventsClass.'::preRemove')], |
|
614 | 7 | 'flush' => [constant($eventsClass.'::postFlush')], |
|
615 | ]; |
||
616 | |||
617 | 7 | foreach ($eventMapping as $event => $doctrineEvents) { |
|
618 | 7 | if (isset($typeConfig['listener'][$event]) && $typeConfig['listener'][$event]) { |
|
619 | 7 | $events = array_merge($events, $doctrineEvents); |
|
620 | } |
||
621 | } |
||
622 | |||
623 | 7 | return $events; |
|
624 | } |
||
625 | |||
626 | /** |
||
627 | * Loads a Type specific Finder. |
||
628 | * |
||
629 | * @param array $typeConfig |
||
630 | * @param ContainerBuilder $container |
||
631 | * @param string $elasticaToModelId |
||
632 | * @param Reference $typeRef |
||
633 | * @param string $indexName |
||
634 | * @param string $typeName |
||
635 | * |
||
636 | * @return string |
||
637 | */ |
||
638 | 11 | private function loadTypeFinder(array $typeConfig, ContainerBuilder $container, $elasticaToModelId, Reference $typeRef, $indexName, $typeName) |
|
665 | |||
666 | /** |
||
667 | * Loads the index manager. |
||
668 | * |
||
669 | * @param ContainerBuilder $container |
||
670 | **/ |
||
671 | private function loadIndexManager(ContainerBuilder $container) |
||
680 | |||
681 | /** |
||
682 | * Makes sure a specific driver has been loaded. |
||
683 | * |
||
684 | * @param ContainerBuilder $container |
||
685 | * @param string $driver |
||
686 | */ |
||
687 | 11 | private function loadDriver(ContainerBuilder $container, $driver) |
|
697 | |||
698 | /** |
||
699 | * Loads and configures the serializer prototype. |
||
700 | * |
||
701 | * @param array $config |
||
702 | * @param ContainerBuilder $container |
||
703 | */ |
||
704 | 1 | private function loadSerializer($config, ContainerBuilder $container) |
|
715 | |||
716 | /** |
||
717 | * Creates a default manager alias for defined default manager or the first loaded driver. |
||
718 | * |
||
719 | * @param string $defaultManager |
||
720 | * @param ContainerBuilder $container |
||
721 | */ |
||
722 | 12 | private function createDefaultManagerAlias($defaultManager, ContainerBuilder $container) |
|
738 | |||
739 | /** |
||
740 | * Returns a reference to a client given its configured name. |
||
741 | * |
||
742 | * @param string $clientName |
||
743 | * |
||
744 | * @return Reference |
||
745 | * |
||
746 | * @throws \InvalidArgumentException |
||
747 | */ |
||
748 | 2 | private function getClient($clientName) |
|
756 | } |
||
757 |
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.