Completed
Pull Request — 2.x (#28)
by Hari
01:57
created

IntlFormatter::format()   C

Complexity

Conditions 9
Paths 96

Size

Total Lines 68
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 9.0509

Importance

Changes 0
Metric Value
dl 0
loc 68
ccs 32
cts 35
cp 0.9143
rs 6.2813
c 0
b 0
f 0
cc 9
eloc 38
nc 96
nop 3
crap 9.0509

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
            } 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
                $string,
82 11
                1
83
            );
84
        }
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
            }
98
99 9
            $values[$i] = $value;
100
        }
101
102
        try {
103 11
            $formatter = new MessageFormatter($locale, $string);
104 10
            if (! $formatter) {
105 10
                $this->throwCannotInstantiateFormatter();
106
            }
107 1
        } 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
            intl_get_error_message(),
126
            intl_get_error_code()
127
        );
128
    }
129
}
130