SimpleMessageFormatter   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 16
eloc 44
c 2
b 0
f 0
dl 0
loc 101
ccs 42
cts 42
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B format() 0 44 7
B pluralize() 0 30 8
A formatList() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Translator;
6
7
use InvalidArgumentException;
8
9
use function count;
10
use function in_array;
11
use function is_int;
12
13
class SimpleMessageFormatter implements MessageFormatterInterface
14
{
15
    /**
16
     * @psalm-suppress MissingClassConstType
17
     */
18
    private const PLURAL_ONE = 'one';
19
20
    /**
21
     * @psalm-suppress MissingClassConstType
22
     */
23
    private const PLURAL_OTHER = 'other';
24
25
    /**
26
     * @psalm-suppress MissingClassConstType
27
     */
28
    private const PLURAL_KEYS = [self::PLURAL_ONE, self::PLURAL_OTHER];
29
30 25
    public function format(string $message, array $parameters, string $locale = 'en-US'): string
31
    {
32 25
        preg_match_all('/{((?>[^{}]+)|(?R))*}/', $message, $matches);
33 25
        $replacements = [];
34
35 25
        foreach ($matches[0] as $match) {
36 24
            $parts = explode(',', $match);
37 24
            $parameter = trim($parts[0], '{} ');
38
39 24
            if ($parameter === '') {
40 4
                throw new InvalidArgumentException('Parameter\'s name can not be empty.');
41
            }
42
43 20
            if (!array_key_exists($parameter, $parameters)) {
44 1
                throw new InvalidArgumentException("\"$parameter\" parameter's value is missing.");
45
            }
46
47 19
            $value = $parameters[$parameter] ?? '';
48
49 19
            if (!is_scalar($value)) {
50 2
                continue;
51
            }
52
53 18
            if (count($parts) === 1) {
54 7
                $replacements[$match] = $value;
55
56 7
                continue;
57
            }
58
59 12
            $format = ltrim($parts[1]);
60 12
            $format = rtrim($format, '}');
61
62
            switch ($format) {
63 12
                case 'plural':
64 11
                    $options = $parts[2] ?? '';
65 11
                    $replacements[$match] = self::pluralize($value, $options);
66
67 6
                    break;
68
                default:
69 2
                    $replacements[$match] = $value;
70
            }
71
        }
72
73 15
        return strtr($message, $replacements);
74
    }
75
76 11
    private static function pluralize(mixed $value, string $options): string
77
    {
78 11
        if (!$options) {
79 2
            throw new InvalidArgumentException('Missing plural keys: ' . self::formatList(self::PLURAL_KEYS) . '.');
80
        }
81
82 9
        if (!is_int($value)) {
83 1
            throw new InvalidArgumentException('Only integer numbers are supported with plural format.');
84
        }
85
86 8
        preg_match_all('/([^{}\s]+)({(.*?)})/', $options, $pluralMatches);
87
88 8
        $map = [];
89 8
        foreach ($pluralMatches[1] as $index => $match) {
90 8
            if (!in_array($match, self::PLURAL_KEYS, true)) {
91 1
                continue;
92
            }
93
94 8
            $map[$match] = $pluralMatches[3][$index];
95
        }
96
97 8
        if (!isset($map[self::PLURAL_ONE])) {
98 1
            throw new InvalidArgumentException('Missing plural key "' . self::PLURAL_ONE . '".');
99
        }
100
101 7
        if (!isset($map[self::PLURAL_OTHER])) {
102 1
            throw new InvalidArgumentException('Missing plural key "' . self::PLURAL_OTHER . '".');
103
        }
104
105 6
        return $value === 1 ? $map[self::PLURAL_ONE] : $map[self::PLURAL_OTHER];
106
    }
107
108
    /**
109
     * @param string[] $items
110
     */
111 2
    private static function formatList(array $items): string
112
    {
113 2
        return implode(', ', array_map(fn (string $value): string => '"' . $value . '"', $items));
114
    }
115
}
116