Completed
Push — master ( 13f2dd...a39436 )
by Tobias
05:16
created

Importer   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 157
Duplicated Lines 9.55 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 23
lcom 1
cbo 5
dl 15
loc 157
ccs 0
cts 82
cp 0
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B extractToCatalogues() 0 28 5
A extractToCatalogue() 0 6 1
B convertSourceLocationsToMessages() 0 23 4
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\Catalogue\MetadataWriter;
17
use Translation\Extractor\Extractor;
18
use Translation\Extractor\Model\SourceCollection;
19
use Translation\Extractor\Model\SourceLocation;
20
use Translation\Bundle\Catalogue\Operation\MetadataAwareMerge;
21
22
/**
23
 * Use extractors to import translations to message catalogues.
24
 *
25
 * @author Tobias Nyholm <[email protected]>
26
 */
27
final class Importer
28
{
29
    /**
30
     * @var Extractor
31
     */
32
    private $extractor;
33
34
    /**
35
     * @var array
36
     */
37
    private $config;
38
39
    /**
40
     * @var MetadataWriter
41
     */
42
    private $metadataWriter;
43
44
    /**
45
     * @param Extractor      $extractor
46
     * @param MetadataWriter $metadataWriter
47
     */
48
    public function __construct(Extractor $extractor, MetadataWriter $metadataWriter)
49
    {
50
        $this->extractor = $extractor;
51
        $this->metadataWriter = $metadataWriter;
52
    }
53
54
    /**
55
     * @param Finder             $finder
56
     * @param MessageCatalogue[] $catalogues
57
     * @param array              $config     {
58
     *
59
     *     @var array $blacklist_domains Blacklist the domains we should exclude. Cannot be used with whitelist.
60
     *     @var array $whitelist_domains Whitlelist the domains we should include. Cannot be used with blacklist.
61
     *     @var string project_root The project root will be removed from the source location.
62
     * }
63
     *
64
     * @param array $errors from extractor, by reference.
65
     *
66
     * @return MessageCatalogue[]
67
     */
68
    public function extractToCatalogues(Finder $finder, array $catalogues, array $config = [], &$errors = [])
69
    {
70
        $this->processConfig($config);
71
        $sourceCollection = $this->extractor->extract($finder);
72
        $errors = $sourceCollection->getErrors();
73
        $results = [];
74
        foreach ($catalogues as $catalogue) {
75
            $target = new MessageCatalogue($catalogue->getLocale());
76
            $this->convertSourceLocationsToMessages($target, $sourceCollection);
77
78
            $merge = new MetadataAwareMerge($catalogue, $target);
79
            $result = $merge->getResult();
80
            $domains = $merge->getDomains();
81
82
            // Mark new messages as new/obsolete
83
            foreach ($domains as $domain) {
84
                foreach ($merge->getNewMessages($domain) as $key => $translation) {
85
                    $this->metadataWriter->write($result, $key, $domain, 'notes', ['content' => 'status:new']);
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...
86
                }
87
                foreach ($merge->getObsoleteMessages($domain) as $key => $translation) {
88
                    $this->metadataWriter->write($result, $key, $domain, 'notes', ['content' => 'status:obsolete']);
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
            }
91
            $results[] = $result;
92
        }
93
94
        return $results;
95
    }
96
97
    /**
98
     * See docs for extractToCatalogues.
99
     *
100
     * @return MessageCatalogue
101
     */
102
    public function extractToCatalogue(Finder $finder, MessageCatalogue $catalogue, array $config = [])
103
    {
104
        $results = $this->extractToCatalogues($finder, [$catalogue], $config);
105
106
        return reset($results);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression reset($results); of type Symfony\Component\Transl...\MessageCatalogue|false adds false to the return on line 106 which is incompatible with the return type documented by Translation\Bundle\Servi...ter::extractToCatalogue of type Symfony\Component\Translation\MessageCatalogue. It seems like you forgot to handle an error condition.
Loading history...
107
    }
108
109
    /**
110
     * @param MessageCatalogue $catalogue
111
     * @param SourceCollection $collection
112
     */
113
    private function convertSourceLocationsToMessages(MessageCatalogue $catalogue, SourceCollection $collection)
114
    {
115
        /** @var SourceLocation $sourceLocation */
116
        foreach ($collection as $sourceLocation) {
117
            $context = $sourceLocation->getContext();
118
            $domain = isset($context['domain']) ? $context['domain'] : 'messages';
119
            // Check with white/black list
120
            if (!$this->isValidDomain($domain)) {
121
                continue;
122
            }
123
124
            $catalogue->set($sourceLocation->getMessage(), null, $domain);
125
            $trimLength = 1 + strlen($this->config['project_root']);
126
127
            $this->metadataWriter->write(
128
                $catalogue,
129
                $sourceLocation->getMessage(),
130
                $domain,
131
                'notes',
132
                ['from' => sprintf('%s:%s', substr($sourceLocation->getPath(), $trimLength), $sourceLocation->getLine()), 'content' => 'file-source']
133
            );
134
        }
135
    }
136
137
    /**
138
     * @param string $domain
139
     *
140
     * @return bool
141
     */
142
    private function isValidDomain($domain)
143
    {
144 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...
145
            return false;
146
        }
147 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...
148
            return false;
149
        }
150
151
        return true;
152
    }
153
154
    /**
155
     * Make sure the configuration is valid.
156
     *
157
     * @param array $config
158
     */
159
    private function processConfig($config)
160
    {
161
        $default = [
162
            'project_root' => '',
163
            'blacklist_domains' => [],
164
            'whitelist_domains' => [],
165
        ];
166
167
        $config = array_merge($default, $config);
168
169 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...
170
            throw new \InvalidArgumentException('Cannot use "blacklist_domains" and "whitelist_domains" at the same time');
171
        }
172
173 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...
174
            throw new \InvalidArgumentException('Config parameter "blacklist_domains" must be an array');
175
        }
176
177 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...
178
            throw new \InvalidArgumentException('Config parameter "whitelist_domains" must be an array');
179
        }
180
181
        $this->config = $config;
182
    }
183
}
184