Completed
Branch BUG/11419/ical-line-endings (79c085)
by
unknown
25:29 queued 12:47
created

I18nRegistry::getLocaleDataMatchingMap()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\assets;
4
5
use EventEspresso\core\domain\DomainInterface;
6
7
/**
8
 * I18nRegistry
9
 * Handles registering translations for registered script handles.
10
 *
11
 * @package EventEspresso\core\services\assets
12
 * @author  Darren Ethier
13
 * @since   $VID:$
14
 */
15
class I18nRegistry
16
{
17
    /**
18
     * @var DomainInterface
19
     */
20
    private $domain;
21
22
    /**
23
     * Will hold all registered i18n scripts.
24
     *
25
     * @var array
26
     */
27
    private $registered_i18n = array();
28
29
30
    /**
31
     * Used to hold queued translations for the chunks loading in a view.
32
     *
33
     * @var array
34
     */
35
    private $queued_handle_translations = array();
36
37
38
    /**
39
     * Obtained from the generated json file from the all javascript using wp.i18n with a map of script handle names to
40
     * translation strings.
41
     *
42
     * @var array
43
     */
44
    private $i18n_map;
45
46
47
    /**
48
     * I18nRegistry constructor.
49
     *
50
     * @param array() $i18n_map  An array of script handle names and the strings translated for those handles.  If not
51
     *                            provided, the class will look for map in root of plugin with filename of
52
     *                            'translation-map.json'.
53
     * @param DomainInterface $domain
54
     */
55
    public function __construct(array $i18n_map = array(), DomainInterface $domain)
56
    {
57
        $this->domain = $domain;
58
        $this->setI18nMap($i18n_map);
59
        add_filter('print_scripts_array', array($this, 'queueI18n'));
60
    }
61
62
63
    /**
64
     * Used to register a script that has i18n strings for its $handle
65
     *
66
     * @param string $handle The script handle reference.
67
     * @param string $domain The i18n domain for the strings.
68
     */
69
    public function registerScriptI18n($handle, $domain = 'event_espresso')
70
    {
71
        $this->registered_i18n[$handle] = $domain;
72
    }
73
74
75
76
    /**
77
     * Callback on print_scripts_array to listen for scripts enqueued and handle setting up the localized data.
78
     *
79
     * @param array $handles Array of registered script handles.
80
     * @return array
81
     */
82
    public function queueI18n(array $handles)
83
    {
84
        if (empty($this->registered_i18n) || empty($this->i18n_map)) {
85
            return $handles;
86
        }
87
        foreach ($handles as $handle) {
88
            $this->queueI18nTranslationsForHandle($handle);
89
        }
90
        if ($this->queued_handle_translations) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->queued_handle_translations of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91
            foreach ($this->queued_handle_translations as $handle => $translations_for_domain) {
92
                $this->registerInlineScript(
93
                    $handle,
94
                    $translations_for_domain['translations'],
95
                    $translations_for_domain['domain']
96
                );
97
            }
98
        }
99
        return $handles;
100
    }
101
102
103
    /**
104
     * Registers inline script with translations for given handle and domain.
105
     *
106
     * @param string $handle       Handle used to register javascript file containing translations.
107
     * @param array  $translations Array of string translations.
108
     * @param string $domain       Domain for translations.  If left empty then strings are registered with the default
109
     *                             domain for the javascript.
110
     */
111
    private function registerInlineScript($handle, array $translations, $domain)
112
    {
113
        $script = $domain ?
114
            'wp.i18n.setLocaleData( ' . wp_json_encode($translations) . ', ' . $domain . ' );' :
115
            'wp.i18n.setLocaleData( ' . wp_json_encode($translations) . ' );';
116
        wp_add_inline_script($handle, $script, 'before');
117
    }
118
119
120
    /**
121
     * Queues up the translation strings for the given handle.
122
     *
123
     * @param string $handle The script handle being queued up.
124
     */
125
    private function queueI18nTranslationsForHandle($handle)
126
    {
127
        if (isset($this->registered_i18n[$handle])) {
128
            $domain = $this->registered_i18n[$handle];
129
            $translations = $this->getJedLocaleDataForDomainAndChunk($handle, $domain);
130
            if (count($translations) > 1) {
131
                $this->queued_handle_translations[$handle] = array(
132
                    'domain'       => $domain,
133
                    'translations' => $translations,
134
                );
135
            }
136
            unset($this->registered_i18n[$handle]);
137
        }
138
    }
139
140
141
    /**
142
     * Sets the internal i18n_map property.
143
     * If $chunk_map is empty or not an array, will attempt to load a chunk map from a default named map.
144
     *
145
     * @param array $i18n_map  If provided, an array of translation strings indexed by script handle names they
146
     *                         correspond to.
147
     */
148
    private function setI18nMap(array $i18n_map)
149
    {
150
        if (empty($i18n_map)) {
151
            $i18n_map = file_exists($this->domain->pluginPath() . 'translation-map.json')
152
                ? json_decode(
153
                        file_get_contents($this->domain->pluginPath() . 'translation-map.json'),
154
                        true
155
                    )
156
                : array();
157
        }
158
        $this->i18n_map = $i18n_map;
159
    }
160
161
162
    /**
163
     * Get the jed locale data for a given $handle and domain
164
     *
165
     * @param string $handle The name for the script handle we want strings returned for.
166
     * @param string $domain The i18n domain.
167
     * @return array
168
     */
169
    protected function getJedLocaleDataForDomainAndChunk($handle, $domain)
170
    {
171
        $translations = $this->getJedLocaleData($domain);
172
        // get index for adding back after extracting strings for this $chunk.
173
        $index = $translations[''];
174
        $translations = $this->getLocaleDataMatchingMap(
175
            $this->getOriginalStringsForHandleFromMap($handle),
176
            $translations
177
        );
178
        $translations[''] = $index;
179
        return $translations;
180
    }
181
182
183
    /**
184
     * Get locale data for given strings from given translations
185
     *
186
     * @param array $string_set   This is the subset of strings (msgIds) we want to extract from the translations array.
187
     * @param array $translations Translation data to extra strings from.
188
     * @return array
189
     */
190
    protected function getLocaleDataMatchingMap(array $string_set, array $translations)
191
    {
192
        if (empty($string_set)) {
193
            return array();
194
        }
195
        // some strings with quotes in them will break on the array_flip, so making sure quotes in the string are
196
        // slashed also filter falsey values.
197
        $string_set = array_unique(array_filter(wp_slash($string_set)));
198
        return array_intersect_key($translations, array_flip($string_set));
199
    }
200
201
202
    /**
203
     * Get original strings to translate for the given chunk from the map
204
     *
205
     * @param string $handle The script handle name to get strings from the map for.
206
     * @return array
207
     */
208
    protected function getOriginalStringsForHandleFromMap($handle)
209
    {
210
        return isset($this->i18n_map[$handle]) ? $this->i18n_map[$handle] : array();
211
    }
212
213
214
    /**
215
     * Returns Jed-formatted localization data.
216
     *
217
     * @param  string $domain Translation domain.
218
     * @return array
219
     */
220
    private function getJedLocaleData($domain)
221
    {
222
        $translations = get_translations_for_domain($domain);
223
224
        $locale = array(
225
            '' => array(
226
                'domain' => $domain,
227
                'lang'   => is_admin() ? get_user_locale() : get_locale(),
228
            ),
229
        );
230
231
        if (! empty($translations->headers['Plural-Forms'])) {
232
            $locale['']['plural_forms'] = $translations->headers['Plural-Forms'];
233
        }
234
235
        foreach ($translations->entries as $msgid => $entry) {
236
            $locale[$msgid] = $entry->translations;
237
        }
238
239
        return $locale;
240
    }
241
}