Passed
Push — master ( 69c6d4...00c898 )
by Alexander
02:17
created

SimpleMessageFormatter::pluralize()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 11
c 0
b 0
f 0
nc 6
nop 2
dl 0
loc 21
ccs 12
cts 12
cp 1
crap 5
rs 9.6111
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Translator;
6
7
use InvalidArgumentException;
8
9
class SimpleMessageFormatter implements MessageFormatterInterface
10
{
11
    private const PLURAL_ONE = 'one';
12
    private const PLURAL_OTHER = 'other';
13
    private const PLURAL_KEYS = [self::PLURAL_ONE, self::PLURAL_OTHER];
14
15 12
    public function format(string $message, array $parameters, string $locale = 'en_US'): string
16
    {
17 12
        preg_match_all('/{((?>[^{}]+)|(?R))*}/', $message, $matches);
18 12
        $replacements = [];
19
20 12
        foreach ($matches[0] as $match) {
21 12
            $parts = explode(',', $match);
22 12
            $parameter = trim($parts[0], '{}');
23
24 12
            if (!isset($parameters[$parameter])) {
25 1
                throw new InvalidArgumentException("\"$parameter\" parameter's value is missing.");
26
            }
27
28 11
            $value = $parameters[$parameter];
29
30 11
            if (!is_scalar($value)) {
31 1
                continue;
32
            }
33
34 10
            if (count($parts) === 1) {
35 3
                $replacements[$match] = $value;
36
37 3
                continue;
38
            }
39
40 8
            $format = ltrim($parts[1]);
41 8
            $format = rtrim($format, '}');
42
43 8
            switch ($format) {
44 8
                case 'plural':
45 7
                    $options = $parts[2];
46 7
                    $replacements[$match] = self::pluralize($value, $options);
47
48 5
                    break;
49
                default:
50 2
                    $replacements[$match] = $value;
51
            }
52
        }
53
54 9
        return strtr($message, $replacements);
55
    }
56
57
    /**
58
     * @param mixed $value
59
     * @param string $options
60
     *
61
     * @return string
62
     */
63 7
    private static function pluralize($value, string $options): string
64
    {
65 7
        if (!is_int($value)) {
66 1
            throw new InvalidArgumentException('Only integer numbers are supported with plural format.');
67
        }
68
69 6
        preg_match_all('/([^{}\s]+)({(.*?)})/', $options, $pluralMatches);
70
71 6
        foreach ($pluralMatches[1] as $match) {
72 6
            if (!in_array($match, self::PLURAL_KEYS, true)) {
73 1
                $keysStr = implode(', ', array_map(fn (string $value): string => '"' . $value . '"', self::PLURAL_KEYS));
74
75 1
                throw new InvalidArgumentException("Invalid plural key - \"$match\". The valid keys are $keysStr.");
76
            }
77
        }
78
79 5
        $map = array_combine($pluralMatches[1], $pluralMatches[3]);
80 5
        $formattedValue = $value . ' ';
81 5
        $formattedValue .= $value === 1 ? $map[self::PLURAL_ONE] : $map[self::PLURAL_OTHER];
82
83 5
        return $formattedValue;
84
    }
85
}
86