Completed
Push — master ( cb2703...d9d040 )
by Tobias
12:13
created

Importer   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 172
Duplicated Lines 8.72 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 89.55%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 6
dl 15
loc 172
ccs 60
cts 67
cp 0.8955
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C extractToCatalogues() 0 41 7
B convertSourceLocationsToMessages() 0 23 5
A getMetadata() 0 4 1
A setMetadata() 0 4 1
B isValidDomain() 6 11 5
C processConfig() 9 24 7

How to fix   Duplicated Code   

Duplicated Code

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
2
3
/*
4
 * This file is part of the PHP Translation package.
5
 *
6
 * (c) PHP Translation team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Translation\Bundle\Service;
13
14
use Symfony\Component\Finder\Finder;
15
use Symfony\Component\Translation\MessageCatalogue;
16
use Translation\Bundle\Model\ImportResult;
17
use Translation\Bundle\Model\Metadata;
18
use Translation\Extractor\Extractor;
19
use Translation\Extractor\Model\SourceCollection;
20
use Translation\Extractor\Model\SourceLocation;
21
use Translation\Bundle\Catalogue\Operation\ReplaceOperation;
22
23
/**
24
 * Use extractors to import translations to message catalogues.
25
 *
26
 * @author Tobias Nyholm <[email protected]>
27
 */
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)
44
    {
45 1
        $this->extractor = $extractor;
46 1
    }
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);
0 ignored issues
show
Compatibility introduced by
$result of type object<Symfony\Component...sageCatalogueInterface> is not a sub-type of object<Symfony\Component...ation\MessageCatalogue>. It seems like you assume a concrete implementation of the interface Symfony\Component\Transl...ssageCatalogueInterface to be always present.

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.

Loading history...
87 1
                    $meta->setState('new');
88 1
                    $this->setMetadata($result, $key, $domain, $meta);
0 ignored issues
show
Compatibility introduced by
$result of type object<Symfony\Component...sageCatalogueInterface> is not a sub-type of object<Symfony\Component...ation\MessageCatalogue>. It seems like you assume a concrete implementation of the interface Symfony\Component\Transl...ssageCatalogueInterface to be always present.

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.

Loading history...
89
                }
90 1
                foreach ($merge->getObsoleteMessages($domain) as $key => $translation) {
91 1
                    $meta = $this->getMetadata($result, $key, $domain);
0 ignored issues
show
Compatibility introduced by
$result of type object<Symfony\Component...sageCatalogueInterface> is not a sub-type of object<Symfony\Component...ation\MessageCatalogue>. It seems like you assume a concrete implementation of the interface Symfony\Component\Transl...ssageCatalogueInterface to be always present.

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.

Loading history...
92 1
                    $meta->setState('obsolete');
93 1
                    $this->setMetadata($result, $key, $domain, $meta);
0 ignored issues
show
Compatibility introduced by
$result of type object<Symfony\Component...sageCatalogueInterface> is not a sub-type of object<Symfony\Component...ation\MessageCatalogue>. It seems like you assume a concrete implementation of the interface Symfony\Component\Transl...ssageCatalogueInterface to be always present.

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.

Loading history...
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
            if (isset($sourceLocation->getContext()['desc'])) {
124
                $meta->addCategory('desc', $sourceLocation->getContext()['desc']);
125
            }
126 1
            $this->setMetadata($catalogue, $key, $domain, $meta);
127
        }
128 1
    }
129
130
    /**
131
     * @param MessageCatalogue $catalogue
132
     * @param $key
133
     * @param $domain
134
     *
135
     * @return Metadata
136
     */
137 1
    private function getMetadata(MessageCatalogue $catalogue, $key, $domain)
138
    {
139 1
        return new Metadata($catalogue->getMetadata($key, $domain));
140
    }
141
142
    /**
143
     * @param MessageCatalogue $catalogue
144
     * @param $key
145
     * @param $domain
146
     * @param Metadata $metadata
147
     */
148 1
    private function setMetadata(MessageCatalogue $catalogue, $key, $domain, Metadata $metadata)
149
    {
150 1
        $catalogue->setMetadata($key, $metadata->toArray(), $domain);
151 1
    }
152
153
    /**
154
     * @param string $domain
155
     *
156
     * @return bool
157
     */
158 1
    private function isValidDomain($domain)
159
    {
160 1 View Code Duplication
        if (!empty($this->config['blacklist_domains']) && in_array($domain, $this->config['blacklist_domains'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
            return false;
162
        }
163 1 View Code Duplication
        if (!empty($this->config['whitelist_domains']) && !in_array($domain, $this->config['whitelist_domains'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
            return false;
165
        }
166
167 1
        return true;
168
    }
169
170
    /**
171
     * Make sure the configuration is valid.
172
     *
173
     * @param array $config
174
     */
175 1
    private function processConfig($config)
176
    {
177
        $default = [
178 1
            'project_root' => '',
179
            'blacklist_domains' => [],
180
            'whitelist_domains' => [],
181
        ];
182
183 1
        $config = array_merge($default, $config);
184
185 1 View Code Duplication
        if (!empty($config['blacklist_domains']) && !empty($config['whitelist_domains'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
            throw new \InvalidArgumentException('Cannot use "blacklist_domains" and "whitelist_domains" at the same time');
187
        }
188
189 1 View Code Duplication
        if (!empty($config['blacklist_domains']) && !is_array($config['blacklist_domains'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
            throw new \InvalidArgumentException('Config parameter "blacklist_domains" must be an array');
191
        }
192
193 1 View Code Duplication
        if (!empty($config['whitelist_domains']) && !is_array($config['whitelist_domains'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
            throw new \InvalidArgumentException('Config parameter "whitelist_domains" must be an array');
195
        }
196
197 1
        $this->config = $config;
198 1
    }
199
}
200