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 |
||
| 28 | final class Importer |
||
| 29 | { |
||
| 30 | /** |
||
| 31 | * @var Extractor |
||
| 32 | */ |
||
| 33 | private $extractor; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var array |
||
| 37 | */ |
||
| 38 | private $config; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @param Extractor $extractor |
||
| 42 | */ |
||
| 43 | 1 | public function __construct(Extractor $extractor) |
|
| 47 | |||
| 48 | /** |
||
| 49 | * @param Finder $finder |
||
| 50 | * @param MessageCatalogue[] $catalogues |
||
| 51 | * @param array $config { |
||
| 52 | * |
||
| 53 | * @var array $blacklist_domains Blacklist the domains we should exclude. Cannot be used with whitelist. |
||
| 54 | * @var array $whitelist_domains Whitelist the domains we should include. Cannot be used with blacklist. |
||
| 55 | * @var string $project_root The project root will be removed from the source location. |
||
| 56 | * } |
||
| 57 | * |
||
| 58 | * @return ImportResult |
||
| 59 | */ |
||
| 60 | 1 | public function extractToCatalogues(Finder $finder, array $catalogues, array $config = []) |
|
| 61 | { |
||
| 62 | 1 | $this->processConfig($config); |
|
| 63 | 1 | $sourceCollection = $this->extractor->extract($finder); |
|
| 64 | 1 | $results = []; |
|
| 65 | 1 | foreach ($catalogues as $catalogue) { |
|
| 66 | 1 | $target = new MessageCatalogue($catalogue->getLocale()); |
|
| 67 | 1 | $this->convertSourceLocationsToMessages($target, $sourceCollection); |
|
| 68 | |||
| 69 | // Remove all SourceLocation and State form catalogue. |
||
| 70 | 1 | foreach ($catalogue->getDomains() as $domain) { |
|
| 71 | 1 | foreach ($catalogue->all($domain) as $key => $translation) { |
|
| 72 | 1 | $meta = $this->getMetadata($catalogue, $key, $domain); |
|
| 73 | 1 | $meta->removeAllInCategory('file-source'); |
|
| 74 | 1 | $meta->removeAllInCategory('state'); |
|
| 75 | 1 | $this->setMetadata($catalogue, $key, $domain, $meta); |
|
| 76 | } |
||
| 77 | } |
||
| 78 | |||
| 79 | 1 | $merge = new ReplaceOperation($target, $catalogue); |
|
| 80 | 1 | $result = $merge->getResult(); |
|
| 81 | 1 | $domains = $merge->getDomains(); |
|
| 82 | |||
| 83 | // Mark new messages as new/obsolete |
||
| 84 | 1 | foreach ($domains as $domain) { |
|
| 85 | 1 | foreach ($merge->getNewMessages($domain) as $key => $translation) { |
|
| 86 | 1 | $meta = $this->getMetadata($result, $key, $domain); |
|
|
|
|||
| 87 | 1 | $meta->setState('new'); |
|
| 88 | 1 | $this->setMetadata($result, $key, $domain, $meta); |
|
| 89 | } |
||
| 90 | 1 | foreach ($merge->getObsoleteMessages($domain) as $key => $translation) { |
|
| 91 | 1 | $meta = $this->getMetadata($result, $key, $domain); |
|
| 92 | 1 | $meta->setState('obsolete'); |
|
| 93 | 1 | $this->setMetadata($result, $key, $domain, $meta); |
|
| 94 | } |
||
| 95 | } |
||
| 96 | 1 | $results[] = $result; |
|
| 97 | } |
||
| 98 | |||
| 99 | 1 | return new ImportResult($results, $sourceCollection->getErrors()); |
|
| 100 | } |
||
| 101 | |||
| 102 | /** |
||
| 103 | * @param MessageCatalogue $catalogue |
||
| 104 | * @param SourceCollection $collection |
||
| 105 | */ |
||
| 106 | 1 | private function convertSourceLocationsToMessages(MessageCatalogue $catalogue, SourceCollection $collection) |
|
| 107 | { |
||
| 108 | /** @var SourceLocation $sourceLocation */ |
||
| 109 | 1 | foreach ($collection as $sourceLocation) { |
|
| 110 | 1 | $context = $sourceLocation->getContext(); |
|
| 111 | 1 | $domain = isset($context['domain']) ? $context['domain'] : 'messages'; |
|
| 112 | // Check with white/black list |
||
| 113 | 1 | if (!$this->isValidDomain($domain)) { |
|
| 114 | continue; |
||
| 115 | } |
||
| 116 | |||
| 117 | 1 | $key = $sourceLocation->getMessage(); |
|
| 118 | 1 | $catalogue->set($key, null, $domain); |
|
| 119 | 1 | $trimLength = 1 + strlen($this->config['project_root']); |
|
| 120 | |||
| 121 | 1 | $meta = $this->getMetadata($catalogue, $key, $domain); |
|
| 122 | 1 | $meta->addCategory('file-source', sprintf('%s:%s', substr($sourceLocation->getPath(), $trimLength), $sourceLocation->getLine())); |
|
| 123 | 1 | $this->setMetadata($catalogue, $key, $domain, $meta); |
|
| 124 | } |
||
| 125 | 1 | } |
|
| 126 | |||
| 127 | /** |
||
| 128 | * @param MessageCatalogue $catalogue |
||
| 129 | * @param $key |
||
| 130 | * @param $domain |
||
| 131 | * |
||
| 132 | * @return Metadata |
||
| 133 | */ |
||
| 134 | 1 | private function getMetadata(MessageCatalogue $catalogue, $key, $domain) |
|
| 138 | |||
| 139 | /** |
||
| 140 | * @param MessageCatalogue $catalogue |
||
| 141 | * @param $key |
||
| 142 | * @param $domain |
||
| 143 | * @param Metadata $metadata |
||
| 144 | */ |
||
| 145 | 1 | private function setMetadata(MessageCatalogue $catalogue, $key, $domain, Metadata $metadata) |
|
| 149 | |||
| 150 | /** |
||
| 151 | * @param string $domain |
||
| 152 | * |
||
| 153 | * @return bool |
||
| 154 | */ |
||
| 155 | 1 | private function isValidDomain($domain) |
|
| 166 | |||
| 167 | /** |
||
| 168 | * Make sure the configuration is valid. |
||
| 169 | * |
||
| 170 | * @param array $config |
||
| 171 | */ |
||
| 172 | 1 | private function processConfig($config) |
|
| 196 | } |
||
| 197 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.