Completed
Pull Request — master (#364)
by Luc
09:08
created

getLanguageStrings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
namespace CultuurNet\UDB3\ReadModel;
4
5
use CultuurNet\UDB3\Language;
6
7
class ConfigurableJsonDocumentLanguageAnalyzer implements JsonDocumentLanguageAnalyzerInterface
8
{
9
    /**
10
     * @var string[]
11
     */
12
    private $translatableProperties;
13
14
    /**
15
     * @param string[] $translatableProperties
16
     *   List of translatable properties (on top level).
17
     */
18
    public function __construct(
19
        array $translatableProperties
20
    ) {
21
        $this->translatableProperties = $translatableProperties;
22
    }
23
24
    /**
25
     * @param JsonDocument $jsonDocument
26
     * @return Language[]
27
     */
28
    public function determineAvailableLanguages(JsonDocument $jsonDocument)
29
    {
30
        $json = $jsonDocument->getBody();
31
        $languageStrings = [];
32
33
        foreach ($this->translatableProperties as $translatableProperty) {
34
            $languageStringsOnProperty = $this->getLanguageStrings($json, $translatableProperty);
35
36
            $languageStrings = array_merge(
37
                $languageStrings,
38
                $languageStringsOnProperty
39
            );
40
        }
41
42
        $languageStrings = array_values(array_unique($languageStrings));
43
44
        return $this->getLanguageStringsAsValueObjects($languageStrings);
45
    }
46
47
    /**
48
     * @param JsonDocument $jsonDocument
49
     * @return Language[]
50
     */
51
    public function determineCompletedLanguages(JsonDocument $jsonDocument)
52
    {
53
        $json = $jsonDocument->getBody();
54
        $languageStrings = [];
55
56
        foreach ($this->translatableProperties as $translatableProperty) {
57
            $languageStringsOnProperty = $this->getLanguageStrings($json, $translatableProperty);
58
59
            if (empty($languageStringsOnProperty)) {
60
                // Property was not found, which means it's not set for the
61
                // original language either. Skip it, as it can't be translated
62
                // without an original value.
63
                continue;
64
            }
65
66
            if ($translatableProperty == $this->translatableProperties[0]) {
67
                $languageStrings = $languageStringsOnProperty;
68
            } else {
69
                $languageStrings = array_intersect($languageStrings, $languageStringsOnProperty);
70
            }
71
        }
72
73
        $languageStrings = array_values(array_unique($languageStrings));
74
75
        return $this->getLanguageStringsAsValueObjects($languageStrings);
76
    }
77
78
    /**
79
     * @param \stdClass $json
80
     * @param string $propertyName
81
     * @return string[]
82
     */
83
    private function getLanguageStrings(\stdClass $json, $propertyName)
84
    {
85
        if (strpos($propertyName, '.') === false) {
86
            return $this->getLanguageStringsFromProperty($json, $propertyName);
87
        } else {
88
            return $this->getLanguageStringsFromNestedProperty($json, $propertyName);
89
        }
90
    }
91
92
    /**
93
     * @param \stdClass $json
94
     * @param string $propertyName
95
     * @return string[]
96
     */
97
    private function getLanguageStringsFromProperty(\stdClass $json, $propertyName)
98
    {
99
        if (!isset($json->{$propertyName})) {
100
            return [];
101
        }
102
103
        return array_keys(
104
            get_object_vars($json->{$propertyName})
105
        );
106
    }
107
108
    /**
109
     * @param \stdClass $json
110
     * @param string $propertyName
111
     * @return string[]
112
     */
113
    private function getLanguageStringsFromNestedProperty(\stdClass $json, $propertyName)
114
    {
115
        $nestedProperties = explode('.', $propertyName);
116
        $traversedProperties = [];
117
        $propertyReference = $json;
118
119
        $languages = [];
120
121
        while ($nestedPropertyName = array_shift($nestedProperties)) {
122
            if ($nestedPropertyName === '[]') {
123
                foreach ($propertyReference as $key => $arrayItem) {
124
                    $remainingPath = implode('.', $nestedProperties);
125
126
                    $recursiveLanguages = $this->getLanguageStringsFromNestedProperty(
127
                        $propertyReference[$key],
128
                        $remainingPath
129
                    );
130
131
                    $languages = array_merge($languages, $recursiveLanguages);
132
                }
133
                return $languages;
134
            }
135
136
            if (!isset($propertyReference->{$nestedPropertyName})) {
137
                // Is either optional or should be handled by a different rule.
138
                return [];
139
            }
140
141
            $propertyReference = $propertyReference->{$nestedPropertyName};
142
            $traversedProperties[] = $nestedPropertyName;
143
        }
144
145
        if (is_object($propertyReference) && $propertyReference) {
146
            return array_keys(get_object_vars($propertyReference));
147
        } else {
148
            return [];
149
        }
150
    }
151
152
    /**
153
     * @param string[] $languageStrings
154
     * @return Language[]
155
     */
156
    private function getLanguageStringsAsValueObjects(array $languageStrings)
157
    {
158
        return array_map(
159
            function ($languageString) {
160
                return new Language($languageString);
161
            },
162
            $languageStrings
163
        );
164
    }
165
}
166