Completed
Push — master ( 00951d...4d50ae )
by Tobias
09:16
created

Importer::convertSourceLocationsToMessages()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 19
cp 0
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 14
nc 5
nop 2
crap 20
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\Extractor\Extractor;
17
use Translation\Extractor\Model\SourceCollection;
18
use Translation\Extractor\Model\SourceLocation;
19
use Translation\Bundle\Catalogue\Operation\MetadataAwareMerge;
20
21
class Importer
22
{
23
    /**
24
     * @var Extractor
25
     */
26
    private $extractor;
27
28
    /**
29
     * @var array
30
     */
31
    private $config;
32
33
    /**
34
     * @param Extractor $extractor
35
     */
36
    public function __construct(Extractor $extractor)
37
    {
38
        $this->extractor = $extractor;
39
    }
40
41
    /**
42
     * @param Finder             $finder
43
     * @param MessageCatalogue[] $catalogue
0 ignored issues
show
Documentation introduced by
There is no parameter named $catalogue. Did you maybe mean $catalogues?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
44
     * @param array              $config    {
45
     *
46
     *     @var array $blacklist_domains Blacklist the domains we should exclude. Cannot be used with whitelist.
47
     *     @var array $whitelist_domains Whitlelist the domains we should include. Cannot be used with blacklist.
48
     *     @var string project_root The project root will be removed from the source location.
49
     * }
50
     *
51
     * @return MessageCatalogue[]
52
     */
53
    public function extractToCatalogues(Finder $finder, array $catalogues, array $config = [])
54
    {
55
        $this->processConfig($config);
56
        $sourceCollection = $this->extractor->extract($finder);
57
        $results = [];
58
        foreach ($catalogues as $catalogue) {
59
            $target = new MessageCatalogue($catalogue->getLocale());
60
            $this->convertSourceLocationsToMessages($target, $sourceCollection);
61
62
            $merge = new MetadataAwareMerge($catalogue, $target);
63
            $result = $merge->getResult();
64
            $domains = $merge->getDomains();
65
66
            // Mark new messages as new/obsolete
67
            foreach ($domains as $domain) {
68
                foreach ($merge->getNewMessages($domain) as $key => $translation) {
69
                    $this->addMetadata($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...
70
                }
71
                foreach ($merge->getObsoleteMessages($domain) as $key => $translation) {
72
                    $this->addMetadata($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...
73
                }
74
            }
75
            $results[] = $result;
76
        }
77
78
        return $results;
79
    }
80
81
    /**
82
     * See docs for extractToCatalogues.
83
     *
84
     * @return MessageCatalogue
85
     */
86
    public function extractToCatalogue(Finder $finder, MessageCatalogue $catalogue, array $config = [])
87
    {
88
        $results = $this->extractToCatalogues($finder, [$catalogue], $config);
89
90
        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 90 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...
91
    }
92
93
    /**
94
     * @param MessageCatalogue $catalogue
95
     * @param SourceCollection $collection
96
     */
97
    private function convertSourceLocationsToMessages(MessageCatalogue $catalogue, SourceCollection $collection)
98
    {
99
        /** @var SourceLocation $sourceLocation */
100
        foreach ($collection as $sourceLocation) {
101
            $context = $sourceLocation->getContext();
102
            $domain = isset($context['domain']) ? $context['domain'] : 'messages';
103
            // Check with white/black list
104
            if (!$this->isValidDomain($domain)) {
105
                continue;
106
            }
107
108
            $catalogue->set($sourceLocation->getMessage(), null, $domain);
109
            $trimLength = 1 + strlen($this->config['project_root']);
110
111
            $this->addMetadata(
112
                $catalogue,
113
                $sourceLocation->getMessage(),
114
                $domain,
115
                'notes',
116
                ['from' => sprintf('%s:%s', substr($sourceLocation->getPath(), $trimLength), $sourceLocation->getLine()), 'content' => 'file-source']
117
            );
118
        }
119
    }
120
121
    /**
122
     * @param MessageCatalogue $catalogue
123
     * @param $sourceLocation
124
     * @param $domain
125
     * @param $type
126
     * @param $value
127
     */
128
    private function addMetadata(MessageCatalogue $catalogue, $key, $domain, $type, $value)
129
    {
130
        $meta = $catalogue->getMetadata($key, $domain);
131
        if (!isset($meta[$type])) {
132
            $meta[$type] = [];
133
        }
134
135
        $meta[$type][] = $value;
136
        $catalogue->setMetadata($key, $meta, $domain);
137
    }
138
139
    /**
140
     * @param string $domain
141
     *
142
     * @return bool
143
     */
144
    private function isValidDomain($domain)
145
    {
146 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...
147
            return false;
148
        }
149 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...
150
            return false;
151
        }
152
153
        return true;
154
    }
155
156
    /**
157
     * Make sure the configuration is valid.
158
     *
159
     * @param array $config
160
     */
161
    private function processConfig($config)
162
    {
163
        $default = [
164
            'project_root' => '',
165
            'blacklist_domains' => [],
166
            'whitelist_domains' => [],
167
        ];
168
169
        $config = array_merge($default, $config);
170
171 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...
172
            throw new \InvalidArgumentException('Cannot use "blacklist_domains" and "whitelist_domains" at the same time');
173
        }
174
175 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...
176
            throw new \InvalidArgumentException('Config parameter "blacklist_domains" must be an array');
177
        }
178
179 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...
180
            throw new \InvalidArgumentException('Config parameter "whitelist_domains" must be an array');
181
        }
182
183
        $this->config = $config;
184
    }
185
}
186