Po::read()   D
last analyzed

Complexity

Conditions 26
Paths 210

Size

Total Lines 106
Code Lines 67

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 67
nc 210
nop 1
dl 0
loc 106
rs 4.1424
c 0
b 0
f 0

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
 * Koch Framework
5
 * Jens-André Koch © 2005 - onwards.
6
 *
7
 * This file is part of "Koch Framework".
8
 *
9
 * License: GNU/GPL v2 or any later version, see LICENSE file.
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace Koch\Localization\Adapter\Gettext;
26
27
/**
28
 * Koch Framework - Class for handling of Gettext (.po) files.
29
 *
30
 * Based on php-msgfmt written by
31
 *
32
 * @author Matthias Bauer
33
 * @copyright 2007 Matthias Bauer
34
 * @license GNU/LGPL 2.1
35
 *
36
 * @link http://wordpress-soc-2007.googlecode.com/svn/trunk/moeffju/php-msgfmt/
37
 */
38
class Po
0 ignored issues
show
Coding Style introduced by
Po does not seem to conform to the naming convention (Utils?$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
39
{
40
    /**
41
     * Reads a Gettext .po file.
42
     *
43
     * @link http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
44
     *
45
     * @param string $file Path to PO file.
46
     *
47
     * @return mixed|bool|array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|array.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
48
     */
49
    public static function read($file)
50
    {
51
        // read .po file
52
        $fh = fopen($file, 'r');
53
54
        if ($fh === false) {
55
            // could not open file resource
56
            return false;
57
        }
58
59
        $result = [];
60
        $temp   = [];
61
        $state  = null;
62
        $fuzzy  = false;
63
64
        // iterate over lines
65
        while (($line = fgets($fh, 65536)) !== false) {
66
            $line = trim($line);
67
68
            if ($line === '') {
69
                continue;
70
            }
71
72
            list($key, $data) = preg_split('/\s/', $line, 2);
73
74
            switch ($key) {
75
                case '#,': // flag...
76
                    $fuzzy = in_array('fuzzy', preg_split('/,\s*/', $data), true);
77
                    // fall-through
78
                case '#':  // translator-comments
79
                case '#.': // extracted-comments
80
                case '#:': // reference...
81
                case '#|': // msgid previous-untranslated-string
82
                    // start a new entry
83
                    if (count($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) {
84
                        if (false === $fuzzy) {
85
                            $result[] = $temp;
86
                        }
87
88
                        $temp  = [];
89
                        $state = null;
90
                        $fuzzy = false;
91
                    }
92
                    break;
93
                case 'msgctxt': // context
94
                case 'msgid': // untranslated-string
95
                case 'msgid_plural': // untranslated-string-plural
96
                    $state        = $key;
97
                    $temp[$state] = $data;
98
                    break;
99
                case 'msgstr': // translated-string
100
                    $state          = 'msgstr';
101
                    $temp[$state][] = $data;
102
                    break;
103
                default:
104
                    if (strpos($key, 'msgstr[') !== false) {
105
                        // translated-string-case-n
106
                        $state          = 'msgstr';
107
                        $temp[$state][] = $data;
108
                    } else {
109
                        // continued lines
110
                        switch ($state) {
111
                            case 'msgctxt':
112
                            case 'msgid':
113
                            case 'msgid_plural':
114
                                $temp[$state] .= "\n" . $line;
115
                                break;
116
                            case 'msgstr':
117
                                $temp[$state][count($temp[$state]) - 1] .= "\n" . $line;
118
                                break;
119
                            default:
120
                                // parse error
121
                                fclose($fh);
122
123
                                return false;
124
                        }
125
                    }
126
                    break;
127
            }
128
        }
129
130
        fclose($fh);
131
132
        // add final entry
133
        if ($state === 'msgstr') {
134
            $result[] = $temp;
135
        }
136
137
        // Cleanup data, merge multiline entries, reindex result for ksort
138
        $temp   = $result;
139
        $result = [];
140
141
        foreach ($temp as $entry) {
142
            foreach ($entry as &$v) {
143
                $v = self::poCleaner($v);
144
145
                if ($v === false) {
146
                    // parse error
147
                    return false;
148
                }
149
            }
150
            $result[$entry['msgid']] = $entry;
151
        }
152
153
        return $result;
154
    }
155
156
    /**
157
     * Cleans the po.
158
     *
159
     * @param string|array $x
160
     *
161
     * @return string Cleaned PO element.
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
162
     */
163
    private static function poCleaner($x)
164
    {
165
        if (true === is_array($x)) {
166
            foreach ($x as $k => $v) {
167
                // WATCH IT! RECURSION!
168
                $x[$k] = self::poCleaner($v);
169
            }
170
        } else {
171
            if ($x[0] === '"') {
172
                $x = mb_substr($x, 1, -1);
173
            }
174
175
            $x = str_replace("\"\n\"", '', $x);
176
            $x = str_replace('$', '\\$', $x);
177
178
            // #\Koch\Debug\Debug:firebug($x);
179
180
            // @todo which use case has this eval?
181
            //$x = @ eval ("return \"$x\";");
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
182
        }
183
184
        return $x;
185
    }
186
}
187