Completed
Pull Request — 2.x (#27)
by
unknown
02:09
created

IntlFormatter::format()   C

Complexity

Conditions 9
Paths 96

Size

Total Lines 68
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 9.1364

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 68
ccs 37
cts 42
cp 0.881
rs 6.2813
cc 9
eloc 38
nc 96
nop 3
crap 9.1364

How to fix   Long Method   

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
 * This file is part of the Aura Project for PHP.
5
 *
6
 * @package Aura.Intl
7
 *
8
 * @license http://opensource.org/licenses/MIT MIT
9
 *
10
 */
11
namespace Aura\Intl;
12
13
use MessageFormatter;
14
use Aura\Intl\Exception;
15
16
/**
17
 *
18
 * Uses php intl extension to format messages
19
 *
20
 * @package Aura.Intl
21
 *
22
 */
23
class IntlFormatter implements FormatterInterface
24
{
25
    /**
26
     *
27
     * Constructor.
28
     *
29
     * @param string $icu_version The current ICU version; mostly used for
30
     * testing.
31
     *
32
     * @throws Exception\IcuVersionTooLow when the Version of ICU installed
33
     * is too low for Aura.Intl to work properly.
34
     *
35
     */
36 12
    public function __construct($icu_version = INTL_ICU_VERSION)
37
    {
38 12
        if (version_compare($icu_version, '4.8') < 0) {
39 1
            throw new Exception\IcuVersionTooLow('ICU Version 4.8 or higher required.');
40
        }
41 11
    }
42
43
    /**
44
     *
45
     * Format the message with the help of php intl extension
46
     *
47
     * @param string $locale
48
     * @param string $string
49
     * @param array $tokens_values
50
     * @return string
51
     * @throws Exception
52
     */
53 11
    public function format($locale, $string, array $tokens_values)
54
    {
55
        // extract tokens and retain sequential positions
56 11
        $tokens = [];
57 11
        $i = 0;
58
59
        // opening brace, followed by the token word characters,
60
        // followed by any non-token word character
61 11
        $regex = '/(\{)([A-Za-z0-9_]+)([\,\}])/m';
62 11
        preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
63
64 11
        foreach ($matches as $match) {
0 ignored issues
show
Bug introduced by
The expression $matches of type null|array<integer,array<integer,string>> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
65
66
            // the token name
67 11
            $key = $match[2];
68 11
            if (! isset($tokens[$key])) {
69 11
                $tokens[$key] = $i;
70 11
                $num = $i;
71 11
                $i++;
72 11
            } else {
73 8
                $num = $tokens[$key];
74
            }
75
76
            // replace just the first occurence;
77
            // other occurrences will get replaced later.
78 11
            $string = preg_replace(
79 11
                "/$match[0]/",
80 11
                '{' . $num . $match[3],
81 11
                $string,
82
                1
83 11
            );
84 11
        }
85
86 11
        $values = [];
87 11
        foreach ($tokens as $token => $i) {
88 11
            if (! isset($tokens_values[$token])) {
89 2
                continue;
90
            }
91
92 9
            $value = $tokens_values[$token];
93
94
            // convert an array to a CSV string
95 9
            if (is_array($value)) {
96 1
                $value = '"' . implode('", "', $value) . '"';
97 1
            }
98
99 9
            $values[$i] = $value;
100 11
        }
101
102
        try {
103 11
            $formatter = new MessageFormatter($locale, $string);
104 11
            if (! $formatter) {
105 1
                $this->throwCannotInstantiateFormatter();
106
            }
107 11
        } catch (\Exception $e) {
108 1
            $this->throwCannotInstantiateFormatter();
109
        }
110
111 10
        $result = $formatter->format($values);
112 10
        if ($result === false) {
113
            throw new Exception\CannotFormat(
114
                $formatter->getErrorMessage(),
115
                $formatter->getErrorCode()
116
            );
117
        }
118
119 10
        return $result;
120
    }
121
122 1
    protected function throwCannotInstantiateFormatter()
123
    {
124 1
        throw new Exception\CannotInstantiateFormatter(
125 1
            intl_get_error_message(),
126 1
            intl_get_error_code()
127 1
        );
128
    }
129
}
130