Completed
Push — in-memory-cache2 ( de4787 )
by André
21:05
created

generateLanguageMaskFromLanguageMap()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 1
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Language MaskGenerator class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Persistence\Legacy\Content\Language;
10
11
use eZ\Publish\SPI\Persistence\Content\Language\Handler as LanguageHandler;
12
13
/**
14
 * Language MaskGenerator.
15
 */
16
class MaskGenerator
17
{
18
    /**
19
     * Language lookup.
20
     *
21
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\Language\Handler
22
     */
23
    protected $languageHandler;
24
25
    /**
26
     * Creates a new Language MaskGenerator.
27
     *
28
     * @param \eZ\Publish\SPI\Persistence\Content\Language\Handler $languageHandler
29
     */
30
    public function __construct(LanguageHandler $languageHandler)
31
    {
32
        $this->languageHandler = $languageHandler;
0 ignored issues
show
Documentation Bug introduced by
$languageHandler is of type object<eZ\Publish\SPI\Pe...ntent\Language\Handler>, but the property $languageHandler was declared to be of type object<eZ\Publish\Core\P...ntent\Language\Handler>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
33
    }
34
35
    /**
36
     * Generates a language mask from the keys of $languages.
37
     *
38
     * @deprecated Move towards using {@see generateLanguageMaskFromLanguageMap()} or the other specific methods.
39
     *
40
     * @param array $languages
41
     *
42
     * @return int
43
     */
44
    public function generateLanguageMask(array $languages)
45
    {
46
        return $this->generateLanguageMaskFromLanguageMap($languages);
47
    }
48
49
    /**
50
     * Generates a language mask from pre-loaded Language Ids.
51
     *
52
     * @param int[] $languageIds
53
     * @param bool $alwaysAvailable
54
     *
55
     * @return int
56
     */
57
    public function generateLanguageMaskFromLanguageIds(array $languageIds, $alwaysAvailable): int
58
    {
59
        // make sure alwaysAvailable part of bit mask always results in 1 or 0
60
        $languageMask = $alwaysAvailable ? 1 : 0;
61
62
        foreach ($languageIds as $languageId) {
63
            $languageMask |= $languageId;
64
        }
65
66
        return $languageMask;
67
    }
68
69
    /**
70
     * Generates a language mask from the keys of $languageMap.
71
     *
72
     * Typically used for ->name values to get language mask directly from such structure.
73
     *
74
     * @param array $languageMap Key values are language code, value is ignored.
75
     *              Exception if 'always-available' key with language value is set, then always available flag is added.
76
     *
77
     * @return int
78
     */
79
    public function generateLanguageMaskFromLanguageMap(array $languageMap): int
80
    {
81
        $mask = 0;
82
        if (isset($languageMap['always-available'])) {
83
            $mask |= $languageMap['always-available'] ? 1 : 0;
84
            unset($languageMap['always-available']);
85
        }
86
87
        $languageList = $this->languageHandler->loadListByLanguageCodes(array_keys($languageMap));
88
        foreach ($languageList as $language) {
89
            $mask |= $language->id;
90
        }
91
92
        return $mask;
93
    }
94
95
    /**
96
     * Generates a language mask from plain array of language codes and always available flag.
97
     *
98
     * @param string[] $languageCodes
99
     * @param bool $isAlwaysAvailable
100
     *
101
     * @return int
102
     */
103
    public function generateLanguageMaskFromLanguageCodes(array $languageCodes, bool $isAlwaysAvailable = false): int
104
    {
105
        $mask = $isAlwaysAvailable ? 1 : 0;
106
107
        $languageList = $this->languageHandler->loadListByLanguageCodes($languageCodes);
108
        foreach ($languageList as $language) {
109
            $mask |= $language->id;
110
        }
111
112
        return $mask;
113
    }
114
115
    /**
116
     * Generates a language indicator from $languageCode and $alwaysAvailable.
117
     *
118
     * @param string $languageCode
119
     * @param bool $alwaysAvailable
120
     *
121
     * @return int
122
     */
123
    public function generateLanguageIndicator($languageCode, $alwaysAvailable)
124
    {
125
        return $this->languageHandler->loadByLanguageCode($languageCode)->id | ($alwaysAvailable ? 1 : 0);
126
    }
127
128
    /**
129
     * Checks if $language is always available in $languages;.
130
     *
131
     * @param string $language
132
     * @param array $languages
133
     *
134
     * @return bool
135
     */
136
    public function isLanguageAlwaysAvailable($language, array $languages): bool
137
    {
138
        return isset($languages['always-available'])
139
           && ($languages['always-available'] == $language)
140
        ;
141
    }
142
143
    /**
144
     * Checks if $languageMask contains the alwaysAvailable bit field.
145
     *
146
     * @param int $languageMask
147
     *
148
     * @return bool
149
     */
150
    public function isAlwaysAvailable($languageMask): bool
151
    {
152
        return (bool)($languageMask & 1);
153
    }
154
155
    /**
156
     * Removes the alwaysAvailable flag from $languageId and returns cleaned up $languageId.
157
     *
158
     * @param int $languageId
159
     *
160
     * @return int
161
     */
162
    public function removeAlwaysAvailableFlag($languageId): int
163
    {
164
        return $languageId & ~1;
165
    }
166
167
    /**
168
     * Extracts every language Ids contained in $languageMask.
169
     *
170
     * @param int $languageMask
171
     *
172
     * @return array Array of language Id
173
     */
174 View Code Duplication
    public function extractLanguageIdsFromMask($languageMask): array
175
    {
176
        $exp = 2;
177
        $result = array();
178
179
        // Decomposition of $languageMask into its binary components.
180
        while ($exp <= $languageMask) {
181
            if ($languageMask & $exp) {
182
                $result[] = $exp;
183
            }
184
185
            $exp *= 2;
186
        }
187
188
        return $result;
189
    }
190
191
    /**
192
     * Extracts Language codes contained in given $languageMask.
193
     *
194
     * @param int $languageMask
195
     *
196
     * @return array
197
     */
198
    public function extractLanguageCodesFromMask($languageMask): array
199
    {
200
        $languageCodes = [];
201
        $languageList = $this->languageHandler->loadList(
202
            $this->extractLanguageIdsFromMask($languageMask)
203
        );
204
        foreach ($languageList as $language) {
205
            $languageCodes[] = $language->languageCode;
206
        }
207
208
        return $languageCodes;
209
    }
210
211
    /**
212
     * Checks if given $languageMask consists of multiple languages.
213
     *
214
     * @param int $languageMask
215
     *
216
     * @return bool
217
     */
218
    public function isLanguageMaskComposite($languageMask): bool
219
    {
220
        // Ignore first bit
221
        $languageMask = $this->removeAlwaysAvailableFlag($languageMask);
222
223
        // Special case
224
        if ($languageMask === 0) {
225
            return false;
226
        }
227
228
        // Return false if power of 2
229
        return (bool)($languageMask & ($languageMask - 1));
230
    }
231
}
232