Transliterate::nullEncoder()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EngineWorks\Templates\Plugins;
6
7
use EngineWorks\Templates\Plugin;
8
9
class Transliterate implements Plugin
10
{
11
    /**
12
     * @return array{tr: string}
13
     */
14 2
    public function getCallablesTable(): array
15
    {
16
        return [
17 2
            'tr' => 'transliterate',
18
        ];
19
    }
20
21
    /** @var callable */
22
    private $defaultEncoder;
23
24
    /**
25
     * Transliterate constructor.
26
     *
27
     * @param callable|null $defaultEncoder If the default encoder is null then a null encoder is used
28
     */
29 44
    public function __construct(callable $defaultEncoder = null)
30
    {
31 44
        $this->setDefaultEncoder($defaultEncoder ? : [static::class, 'nullEncoder']);
32
    }
33
34
    /**
35
     * Uses a message and replace its keywords with the provided in $arguments
36
     *
37
     * The message can be an object, it will be translated to a string using valueToSting
38
     * The message should include the keywords to replace in curly braces, like:
39
     * Welcome to {city}, enjoy!
40
     *
41
     * Every argument that is included into the message is evaluated to a string
42
     * (using valueToString) and then is passed to the encoder.
43
     *
44
     * If the encoder is null then uses the default encoder.
45
     *
46
     * @param string $message String with elements using '{key}' template
47
     * @param array<string, mixed> $arguments Key/value array with the replacements
48
     * @param callable|null $encoder function to use for encode
49
     */
50 12
    public function transliterate(string $message, array $arguments = [], callable $encoder = null): string
51
    {
52
        // put message as string
53 12
        $message = $this->valueToString($message);
54
        // if there are no arguments then exit
55 12
        if ('' === $message || 0 == count($arguments)) {
56 1
            return $message;
57
        }
58
        // create encoded arguments (only included if they exist in matches)
59 11
        $encodedArguments = [];
60 11
        $encoder = ($encoder) ? : $this->getDefaultEncoder();
61 11
        foreach ($arguments as $key => $value) {
62 11
            $transKey = '{' . $key . '}';
63 11
            if (false === strpos($message, $transKey)) {
64 2
                continue;
65
            }
66 9
            $encodedArguments[$transKey] = call_user_func($encoder, $this->valueToString($value));
67
        }
68
        // if there are any encoded arguments then exit
69 11
        if (! count($encodedArguments)) {
70 2
            return $message;
71
        }
72
        // translit using strtr php function
73 9
        return strtr($message, $encodedArguments);
74
    }
75
76
    /**
77
     * Retrieve the keys inside the curly braces
78
     * If the keys are duplicated they are removed, therefore,
79
     * if you need consecutive keys then use array_values function
80
     *
81
     * @return string[]
82
     */
83 28
    public function getCurlyBracesKeys(string $message): array
84
    {
85 28
        if ('' === trim($message)) {
86 1
            return [];
87
        }
88
        // preg_match_all return 0 if not found, false on error
89 27
        if (! preg_match_all('/({(?<={)[^{}\r\n]+?(?=})})/U', $message, $matches)) {
90 9
            return [];
91
        }
92 18
        return array_unique($matches[0]);
93
    }
94
95
    /**
96
     * Convert a value to string, if the value is:
97
     * scalar or object with method __toString() then the string cast
98
     * array or traversable then iterates the object converting every member and concat the result
99
     * else empty string
100
     *
101
     * @param mixed $value
102
     */
103 12
    public function valueToString($value): string
104
    {
105 12
        if (is_null($value) || is_scalar($value) || (is_object($value) && is_callable([$value, '__toString']))) {
106 12
            return (string) $value;
107
        }
108 2
        if (is_iterable($value)) {
109 1
            $buffer = [];
110 1
            foreach ($value as $innerValue) {
111 1
                $buffer[] = $this->valueToString($innerValue);
112
            }
113 1
            return implode('', $buffer);
114
        }
115 1
        return '';
116
    }
117
118 12
    public function getDefaultEncoder(): callable
119
    {
120 12
        return $this->defaultEncoder;
121
    }
122
123
    /**
124
     * @param callable(string):string $defaultEncoder
125
     */
126 44
    public function setDefaultEncoder(callable $defaultEncoder): void
127
    {
128 44
        $this->defaultEncoder = $defaultEncoder;
129
    }
130
131
    /**
132
     * Function to setup a null encoder
133
     */
134 1
    public static function nullEncoder(string $string): string
135
    {
136 1
        return $string;
137
    }
138
}
139