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  | 
            ||
| 19 | abstract class AbstractRepositoryFactory implements RepositoryFactory  | 
            ||
| 20 | { | 
            ||
| 21 | /**  | 
            ||
| 22 | * The list of DocumentRepository instances.  | 
            ||
| 23 | *  | 
            ||
| 24 | * @var ObjectRepository[]  | 
            ||
| 25 | */  | 
            ||
| 26 | private $repositoryList = [];  | 
            ||
| 27 | |||
| 28 | 356 | /**  | 
            |
| 29 |      * {@inheritdoc} | 
            ||
| 30 | 356 | */  | 
            |
| 31 | 356 | public function getRepository(DocumentManager $documentManager, string $documentName) : ObjectRepository  | 
            |
| 32 |     { | 
            ||
| 33 | 356 | $metadata = $documentManager->getClassMetadata($documentName);  | 
            |
| 34 | 168 | $hashKey = $metadata->getName() . spl_object_hash($documentManager);  | 
            |
| 
                                                                                                    
                        
                         | 
                |||
| 35 | |||
| 36 |         if (isset($this->repositoryList[$hashKey])) { | 
            ||
| 37 | 356 | return $this->repositoryList[$hashKey];  | 
            |
| 38 | }  | 
            ||
| 39 | 356 | ||
| 40 | $repository = $this->createRepository($documentManager, ltrim($documentName, '\\'));  | 
            ||
| 41 | 356 | ||
| 42 | $this->repositoryList[$hashKey] = $repository;  | 
            ||
| 43 | |||
| 44 | return $repository;  | 
            ||
| 45 | }  | 
            ||
| 46 | |||
| 47 | /**  | 
            ||
| 48 | * Create a new repository instance for a document class.  | 
            ||
| 49 | 356 | *  | 
            |
| 50 | * @return ObjectRepository|GridFSRepository|ViewRepository  | 
            ||
| 51 | 356 | */  | 
            |
| 52 | protected function createRepository(DocumentManager $documentManager, string $documentName) : ObjectRepository  | 
            ||
| 53 | 356 |     { | 
            |
| 54 | 13 | $metadata = $documentManager->getClassMetadata($documentName);  | 
            |
| 55 | 348 | ||
| 56 | 12 | $repositoryClassName = $metadata->isFile  | 
            |
| 57 | ? $documentManager->getConfiguration()->getDefaultGridFSRepositoryClassName()  | 
            ||
| 58 | 337 | : $documentManager->getConfiguration()->getDefaultDocumentRepositoryClassName();  | 
            |
| 59 | |||
| 60 |         if ($metadata->customRepositoryClassName) { | 
            ||
| 61 | 356 | $repositoryClassName = $metadata->customRepositoryClassName;  | 
            |
| 62 | }  | 
            ||
| 63 | |||
| 64 |         switch (true) { | 
            ||
| 65 | case $metadata->isFile:  | 
            ||
| 66 | View Code Duplication |                 if (! is_a($repositoryClassName, GridFSRepository::class, true)) { | 
            |
| 67 | throw MappingException::invalidRepositoryClass($documentName, $repositoryClassName, GridFSRepository::class);  | 
            ||
| 68 | }  | 
            ||
| 69 | break;  | 
            ||
| 70 | |||
| 71 | case $metadata->isView():  | 
            ||
| 72 | View Code Duplication |                 if (! is_a($repositoryClassName, ViewRepository::class, true)) { | 
            |
| 73 | throw MappingException::invalidRepositoryClass($documentName, $repositoryClassName, ViewRepository::class);  | 
            ||
| 74 | }  | 
            ||
| 75 | break;  | 
            ||
| 76 | |||
| 77 | case $metadata->isEmbeddedDocument:  | 
            ||
| 78 | throw MongoDBException::cannotCreateRepository($documentName);  | 
            ||
| 79 | break;  | 
            ||
| 80 | |||
| 81 | case $metadata->isMappedSuperclass:  | 
            ||
| 82 | default:  | 
            ||
| 83 | View Code Duplication |                 if (! is_a($repositoryClassName, DocumentRepository::class, true)) { | 
            |
| 84 | throw MappingException::invalidRepositoryClass($documentName, $repositoryClassName, DocumentRepository::class);  | 
            ||
| 85 | }  | 
            ||
| 86 | break;  | 
            ||
| 87 | }  | 
            ||
| 88 | |||
| 89 | return $this->instantiateRepository($repositoryClassName, $documentManager, $metadata);  | 
            ||
| 90 | }  | 
            ||
| 91 | |||
| 92 | /**  | 
            ||
| 93 | * Instantiates requested repository.  | 
            ||
| 94 | */  | 
            ||
| 95 | abstract protected function instantiateRepository(string $repositoryClassName, DocumentManager $documentManager, ClassMetadata $metadata) : ObjectRepository;  | 
            ||
| 96 | }  | 
            ||
| 97 |