Completed
Push — development ( a150a5...f82eb6 )
by Andrij
17:01
created

php-mo.php ➔ phpmo_parse_po_file()   D

Complexity

Conditions 22
Paths 208

Size

Total Lines 96
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 22
eloc 56
c 1
b 0
f 0
nc 208
nop 1
dl 0
loc 96
rs 4.2688

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * php.mo 0.1 by Joss Crowcroft (http://www.josscrowcroft.com)
5
 *
6
 * Converts gettext translation '.po' files to binary '.mo' files in PHP.
7
 *
8
 * Usage:
9
 * <?php require('php-mo.php'); phpmo_convert( 'input.po', [ 'output.mo' ] ); ?>
10
 *
11
 * NB:
12
 * - If no $output_file specified, output filename is same as $input_file (but .mo)
13
 * - Returns true/false for success/failure
14
 * - No warranty, but if it breaks, please let me know
15
 *
16
 * More info:
17
 * https://github.com/josscrowcroft/php.mo
18
 *
19
 * Based on php-msgfmt by Matthias Bauer (Copyright � 2007), a command-line PHP tool
20
 * for converting .po files to .mo.
21
 * (http://wordpress-soc-2007.googlecode.com/svn/trunk/moeffju/php-msgfmt/msgfmt.php)
22
 *
23
 * License: GPL v3 http://www.opensource.org/licenses/gpl-3.0.html
24
 */
25
26
/**
27
 * The main .po to .mo function
28
 * @param string $input
29
 */
30
function phpmo_convert($input, $output = false) {
31
    //    var_dumps_exit($input);
32
    if (!$output) {
33
        $output = str_replace('.po', '.mo', $input);
34
    }
35
36
    $hash = phpmo_parse_po_file($input);
37
    if ($hash === false) {
38
        return false;
39
    } else {
40
        phpmo_write_mo_file($hash, $output);
41
        return true;
42
    }
43
}
44
45
function phpmo_clean_helper($x) {
46
47
    if (is_array($x)) {
48
        foreach ($x as $k => $v) {
49
            //            $v_tmp = mb_substr($v, 1, mb_strlen($v) - 2);
50
            //            $v = str_replace('"', '\"', $v_tmp);
51
            $x[$k] = phpmo_clean_helper($v);
52
        }
53
    } else {
54
        $v = $x;
55
        $v_tmp = mb_substr($v, 1, mb_strlen($v) - 2);
56
        $v = str_replace('"', '\"', $v_tmp);
0 ignored issues
show
Unused Code introduced by
$v 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...
57
        //        var_dumps($v);
58
        $v = $x;
0 ignored issues
show
Unused Code introduced by
$v 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...
59
        if ($x[0] == '"') {
60
            $x = substr($x, 1, -1);
61
        }
62
        $x = str_replace("\"\n\"", '', $x);
63
        $x = str_replace('$', '\\$', $x);
64
        //        $x = @ eval("return \"$x\";");
65
        //        var_dumps($x);
66
    }
67
    return $x;
68
}
69
70
/* Parse gettext .po files. */
71
/* @link http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files */
72
73
function phpmo_parse_po_file($in) {
74
    // read .po file
75
    $fc = file_get_contents($in);
76
    // normalize newlines
77
    $fc = str_replace(
78
        array(
79
        "\r\n",
80
        "\r"
81
            ),
82
        array(
83
            "\n",
84
            "\n"
85
            ),
86
        $fc
87
    );
88
89
    // results array
90
    $hash = array();
91
    // temporary array
92
    $temp = array();
93
    // state
94
    $state = null;
95
    $fuzzy = false;
96
97
    // iterate over lines
98
    foreach (explode("\n", $fc) as $line) {
99
        $line = trim($line);
100
        if ($line === '') {
101
            continue;
102
        }
103
104
        list ($key, $data) = explode(' ', $line, 2);
105
106
        switch ($key) {
107
            case '#,' : // flag...
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
108
                $fuzzy = in_array('fuzzy', preg_split('/,\s*/', $data));
109
            case '#' : // translator-comments
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
110
            case '#.' : // extracted-comments
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
111
            case '#:' : // reference...
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
112
            case '#~' : // reference...
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
113
            case '#|' : // msgid previous-untranslated-string
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
114
                // start a new entry
115
                if (sizeof($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) {
0 ignored issues
show
introduced by
sizeof() is a function name alias, use count() instead
Loading history...
116
                    if (!$fuzzy) {
117
                        $hash[] = $temp;
118
                    }
119
                    $temp = array();
120
                    $state = null;
121
                    $fuzzy = false;
122
                }
123
                break;
0 ignored issues
show
Coding Style introduced by
Case breaking statements must be followed by a single blank line
Loading history...
124
            case 'msgctxt' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
125
                // context
126
            case 'msgid' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
127
                // untranslated-string
128
            case 'msgid_plural' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
129
                // untranslated-string-plural
130
                $state = $key;
131
                $temp[$state] = $data;
132
                break;
0 ignored issues
show
Coding Style introduced by
Case breaking statements must be followed by a single blank line
Loading history...
133
            case 'msgstr' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement
Loading history...
134
                // translated-string
135
                $state = 'msgstr';
136
                if ($data) {
137
                    $temp[$state][] = $data;
138
                }
139
140
                break;
141
        }
142
    }
143
144
    // add final entry
145
    if ($state == 'msgstr') {
146
        $hash[] = $temp;
147
    }
148
149
    // Cleanup data, merge multiline entries, reindex hash for ksort
150
    $temp = $hash;
151
    $hash = array();
152
    foreach ($temp as $entry) {
153
        foreach ($entry as & $v) {
154
            $v = phpmo_clean_helper($v);
155
            //            var_dumps($v);
156
            if ($v === FALSE) {
157
                // parse error
158
                continue;
159
                //                return FALSE;
160
            }
161
        }
162
163
        $hash[$entry['msgid']] = $entry;
164
    }
165
    //    var_dumps($hash);
166
    //exit;
167
    return $hash;
168
}
169
170
/* Write a GNU gettext style machine object. */
171
/* @link http://www.gnu.org/software/gettext/manual/gettext.html#MO-Files */
172
173
function phpmo_write_mo_file($hash, $out) {
174
    // sort by msgid
175
    ksort($hash, SORT_STRING);
176
    // our mo file data
177
    $mo = '';
178
    // header data
179
    $offsets = array();
180
    $ids = '';
181
    $strings = '';
182
183
    foreach ($hash as $entry) {
184
        $id = $entry['msgid'];
185
        if (isset($entry['msgid_plural'])) {
186
            $id .= "\x00" . $entry['msgid_plural'];
187
        }
188
        // context is merged into id, separated by EOT (\x04)
189
        if (array_key_exists('msgctxt', $entry)) {
190
            $id = $entry['msgctxt'] . "\x04" . $id;
191
        }
192
        // plural msgstrs are NUL-separated
193
        foreach ($entry['msgstr'] as $key => $msgstr) {
194
            if (!$msgstr) {
195
                unset($entry['msgstr'][$key]);
196
            }
197
        }
198
199
        $str = implode("\x00", $entry['msgstr']);
200
        // keep track of offsets
201
        $offsets[] = array(
202
            strlen(
203
                $ids
204
            ), strlen($id), strlen($strings), strlen($str));
205
            // plural msgids are not stored (?)
206
            $ids .= $id . "\x00";
207
            $strings .= $str . "\x00";
208
    }
209
210
    // keys start after the header (7 words) + index tables ($#hash * 4 words)
211
    $key_start = 7 * 4 + sizeof($hash) * 4 * 4;
0 ignored issues
show
introduced by
sizeof() is a function name alias, use count() instead
Loading history...
212
    // values start right after the keys
213
    $value_start = $key_start + strlen($ids);
214
    // first all key offsets, then all value offsets
215
    $key_offsets = array();
216
    $value_offsets = array();
217
    // calculate
218
    foreach ($offsets as $v) {
219
        list ($o1, $l1, $o2, $l2) = $v;
220
        $key_offsets[] = $l1;
221
        $key_offsets[] = $o1 + $key_start;
222
        $value_offsets[] = $l2;
223
        $value_offsets[] = $o2 + $value_start;
224
    }
225
    $offsets = array_merge($key_offsets, $value_offsets);
226
227
    // write header
228
    $mo .= pack(
229
        'Iiiiiii',
230
        0x950412de, // magic number
231
        0, // version
232
        sizeof($hash), // number of entries in the catalog
0 ignored issues
show
introduced by
sizeof() is a function name alias, use count() instead
Loading history...
233
        7 * 4, // key index offset
234
        7 * 4 + sizeof($hash) * 8, // value index offset,
0 ignored issues
show
introduced by
sizeof() is a function name alias, use count() instead
Loading history...
235
        0, // hashtable size (unused, thus 0)
236
        $key_start // hashtable offset
237
    );
238
    // offsets
239
    foreach ($offsets as $offset) {
240
        $mo .= pack('i', $offset);
241
    }
242
    // ids
243
    $mo .= $ids;
244
    // strings
245
    $mo .= $strings;
246
247
    $directory = dirname($out);
248
    $current_mo_file_name = array_pop(glob($directory . '/*.mo'));
0 ignored issues
show
Bug introduced by
glob($directory . '/*.mo') cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
249
    if (!$current_mo_file_name) {
250
        $current_mo_file_name = array_pop(glob($directory . '\*.mo'));
0 ignored issues
show
Bug introduced by
glob($directory . '\\*.mo') cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
251
        if (!$current_mo_file_name) {
252
            $current_mo_file_name = $out;
253
        }
254
    }
255
256
    $old_mo_files = glob($directory . '/*.mo');
257
    if ($old_mo_files && is_array($old_mo_files)) {
258
        foreach ($old_mo_files as $file) {
259
            unlink($file);
260
        }
261
    }
262
263
    $addition_time = time();
264
    if (!preg_match('/[\d]+/', $current_mo_file_name)) {
265
        $new_mo_file_name = str_replace('.mo', '_' . $addition_time . '.mo', $current_mo_file_name);
266
    } else {
267
        $new_mo_file_name = preg_replace('/_[\d]+/', '_' . $addition_time, $current_mo_file_name);
268
    }
269
270
    //    rename($current_mo_file_name, $new_mo_file_name);
271
272
    file_put_contents($new_mo_file_name, $mo);
273
274
    chmod($new_mo_file_name, 0777);
275
}