StringFormatter::formatSilent()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 4
dl 0
loc 7
rs 10
1
<?php
2
3
namespace Smoren\StringFormatter;
4
5
use Smoren\Schemator\Components\NestedAccessor;
6
use Smoren\Schemator\Exceptions\PathNotExistException;
7
8
/**
9
 * StringFormatter class
10
 */
11
class StringFormatter
12
{
13
    public const DEFAULT_REGEXP = '/\{([A-Za-z0-9\-_\.]+)\}/';
14
    public const DEFAULT_PATH_DELIMITER = '.';
15
16
    /**
17
     * Formats string with given params
18
     * @param string $input input string
19
     * @param array<string, mixed> $params params map
20
     * @param bool $silent if true don't throw exception with catching errors
21
     * @param non-empty-string $regexp regular expression for masked params
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
22
     * @param non-empty-string $pathDelimiter path delimiter for nested param paths
23
     * @return string result string with replaced params masks
24
     * @throws StringFormatterException if not silent and some errors catched
25
     */
26
    public static function format(
27
        string $input,
28
        array $params,
29
        bool $silent = false,
30
        string $regexp = self::DEFAULT_REGEXP,
31
        string $pathDelimiter = self::DEFAULT_PATH_DELIMITER
32
    ): string {
33
        $accessor = new NestedAccessor($params, $pathDelimiter);
34
        $keyMap = static::findKeys($input, $regexp);
35
36
        $notFoundKeys = [];
37
        foreach($keyMap as $key => &$path) {
38
            try {
39
                $path = $accessor->get($path);
40
            } catch(PathNotExistException $e) {
41
                $notFoundKeys[] = $path;
42
                unset($keyMap[$key]);
43
            }
44
        }
45
        unset($path);
46
47
        if(!$silent && count($notFoundKeys)) {
48
            throw new StringFormatterException(
49
                'some keys not found in params array',
50
                StringFormatterException::ERROR_KEYS_NOT_FOUND,
51
                null,
52
                array_values($notFoundKeys)
53
            );
54
        }
55
56
        return str_replace(array_keys($keyMap), array_values($keyMap), $input);
57
    }
58
59
    /**
60
     * Formats string with given params in silent mode
61
     * @param string $input input string
62
     * @param array<string, mixed> $params params map
63
     * @param non-empty-string $regexp regular expression for masked params
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
64
     * @param non-empty-string $pathDelimiter path delimiter for nested param paths
65
     * @return string result string with replaced params masks
66
     */
67
    public static function formatSilent(
68
        string $input,
69
        array $params,
70
        string $regexp = self::DEFAULT_REGEXP,
71
        string $pathDelimiter = self::DEFAULT_PATH_DELIMITER
72
    ): string {
73
        return static::format($input, $params, true, $regexp, $pathDelimiter);
74
    }
75
76
    /**
77
     * Returns map of found keys to replace with params map
78
     * @param string $input input string
79
     * @param string $regexp regular expression for masked params
80
     * @return string[]
81
     */
82
    protected static function findKeys(string $input, string $regexp): array
83
    {
84
        preg_match_all($regexp, $input, $matches);
85
        $result = array_combine($matches[0] ?? [], $matches[1] ?? []);
86
        if(!$result) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
87
            return [];
88
        }
89
        return $result;
90
    }
91
}
92