Completed
Push — master ( 305e31...928d5d )
by Karel
10:10
created

ReplaceOperation   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 88.89%

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 4
dl 0
loc 139
ccs 56
cts 63
cp 0.8889
rs 9.76
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
C processDomain() 0 61 14
A getMetadata() 0 9 2
B mergeMetadata() 0 22 7
B doMergeMetadata() 0 23 8
A isArrayAssociative() 0 8 2
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\Catalogue\Operation;
13
14
use Symfony\Component\Translation\Catalogue\AbstractOperation;
15
use Symfony\Component\Translation\MessageCatalogueInterface;
16
use Symfony\Component\Translation\MetadataAwareInterface;
17
18
/**
19
 * This will merge and replace all values in $target with values from $source.
20
 * It is the equivalent of running array_merge($target, $source). When in conflict,
21
 * always take values from $source.
22
 *
23
 * This operation is metadata aware. It will do the same recursive merge on metadata.
24
 *
25
 * all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
26
 * new = all ∖ target = {x: x ∈ source ∧ x ∉ target}
27
 * obsolete = target ∖ all = {x: x ∈ target ∧ x ∉ source}
28
 *
29
 * @author Tobias Nyholm <[email protected]>
30
 */
31
final class ReplaceOperation extends AbstractOperation
32
{
33 6
    protected function processDomain($domain)
34
    {
35 6
        $this->messages[$domain] = [
36
            'all' => [],
37
            'new' => [],
38
            'obsolete' => [],
39
        ];
40 6
        if (defined(sprintf('%s::INTL_DOMAIN_SUFFIX', MessageCatalogueInterface::class))) {
41 6
            $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
42
        } else {
43
            $intlDomain = $domain;
44
        }
45
46 6
        foreach ($this->source->all($domain) as $id => $message) {
47 5
            $messageDomain = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
48 5
            $this->messages[$domain]['all'][$id] = $message;
49 5
            $this->result->add([$id => $message], $messageDomain);
50
51 5
            if (!$this->target->has($id, $domain)) {
52
                // No merge required
53 5
                $this->messages[$domain]['new'][$id] = $message;
54 5
                $resultMeta = $this->getMetadata($this->source, $messageDomain, $id);
55
            } else {
56
                // Merge required
57 5
                $resultMeta = null;
0 ignored issues
show
Unused Code introduced by
$resultMeta is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
58 5
                $sourceMeta = $this->getMetadata($this->source, $messageDomain, $id);
59 5
                $targetMeta = $this->getMetadata($this->target, $this->target->defines($id, $intlDomain) ? $intlDomain : $domain, $id);
60 5
                if (is_array($sourceMeta) && is_array($targetMeta)) {
61
                    // We can only merge meta if both is an array
62 1
                    $resultMeta = $this->mergeMetadata($sourceMeta, $targetMeta);
63 4
                } elseif (!empty($sourceMeta)) {
64 1
                    $resultMeta = $sourceMeta;
65
                } else {
66
                    // Assert: true === empty($sourceMeta);
67 3
                    $resultMeta = $targetMeta;
68
                }
69
            }
70
71 5
            if (!empty($resultMeta)) {
72 2
                $this->result->setMetadata($id, $resultMeta, $messageDomain);
73
            }
74
        }
75
76 6
        foreach ($this->target->all($domain) as $id => $message) {
77 5
            if ($this->result->has($id, $domain)) {
78
                // We've already merged this
79
                // That message was in source
80 5
                continue;
81
            }
82
83 5
            $messageDomain = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
84 5
            $this->messages[$domain]['all'][$id] = $message;
85 5
            $this->messages[$domain]['obsolete'][$id] = $message;
86 5
            $this->result->add([$id => $message], $messageDomain);
87
88 5
            $resultMeta = $this->getMetadata($this->target, $messageDomain, $id);
89 5
            if (!empty($resultMeta)) {
90 2
                $this->result->setMetadata($id, $resultMeta, $messageDomain);
91
            }
92
        }
93 6
    }
94
95
    /**
96
     * @return array|null|string|mixed Can return anything..
97
     */
98 5
    private function getMetadata(MessageCatalogueInterface $catalogue, string $domain, string $key = '')
99
    {
100 5
        if (!$this->target instanceof MetadataAwareInterface) {
101
            return [];
102
        }
103
104
        /* @var MetadataAwareInterface $catalogue */
105 5
        return $catalogue->getMetadata($key, $domain);
106
    }
107
108
    /**
109
     * @param array|null $source
110
     * @param array|null $target
111
     *
112
     * @return array
113
     */
114 1
    private function mergeMetadata($source, $target)
115
    {
116 1
        if (empty($source) && empty($target)) {
117
            return [];
118
        }
119
120 1
        if (empty($source)) {
121
            return $target;
122
        }
123
124 1
        if (empty($target)) {
125
            return $source;
126
        }
127
128 1
        if (!is_array($source) || !is_array($target)) {
129
            return $source;
130
        }
131
132 1
        $result = $this->doMergeMetadata($source, $target);
133
134 1
        return $result;
135
    }
136
137 1
    private function doMergeMetadata(array $source, array $target)
138
    {
139 1
        $isTargetArrayAssociative = $this->isArrayAssociative($target);
140 1
        foreach ($target as $key => $value) {
141 1
            if ($isTargetArrayAssociative) {
142 1
                if (isset($source[$key]) && $source[$key] !== $value) {
143 1
                    if (is_array($source[$key]) && is_array($value)) {
144
                        // If both arrays, do recursive call
145 1
                        $source[$key] = $this->doMergeMetadata($source[$key], $value);
146
                    }
147
                    // Else, use value form $source
148
                } else {
149
                    // Add new value
150 1
                    $source[$key] = $value;
151
                }
152
                // if sequential
153 1
            } elseif (!in_array($value, $source)) {
154 1
                $source[] = $value;
155
            }
156
        }
157
158 1
        return $source;
159
    }
160
161 1
    public function isArrayAssociative(array $arr)
162
    {
163 1
        if ([] === $arr) {
164
            return false;
165
        }
166
167 1
        return array_keys($arr) !== range(0, count($arr) - 1);
168
    }
169
}
170