summaryrefslogtreecommitdiffstats
path: root/vendor/ipl/html/src/FormattedString.php
blob: 1ef9b5b8248809a1ec402375a27050af2fdbfc8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php

namespace ipl\Html;

use Exception;
use InvalidArgumentException;

use function ipl\Stdlib\get_php_type;

/**
 * {@link sprintf()}-like formatted HTML string supporting lazy rendering of {@link ValidHtml} element arguments
 *
 * # Example Usage
 * ```
 * $info = new FormattedString(
 *     'Follow the %s for more information on %s',
 *     [
 *         new Link('doc/html', 'HTML documentation'),
 *         Html::tag('strong', 'HTML elements')
 *     ]
 * );
 * ```
 */
class FormattedString implements ValidHtml
{
    /** @var ValidHtml[] */
    protected $args = [];

    /** @var ValidHtml */
    protected $format;

    /**
     * Create a new {@link sprintf()}-like formatted HTML string
     *
     * @param string   $format
     * @param iterable $args
     *
     * @throws InvalidArgumentException If arguments given but not iterable
     */
    public function __construct($format, $args = null)
    {
        $this->format = Html::wantHtml($format);

        if ($args !== null) {
            if (! is_iterable($args)) {
                throw new InvalidArgumentException(sprintf(
                    '%s expects parameter two to be iterable, got %s instead',
                    __METHOD__,
                    get_php_type($args)
                ));
            }

            foreach ($args as $key => $val) {
                if (! is_scalar($val) || (is_string($val) && ! is_numeric($val))) {
                    $val = Html::wantHtml($val);
                }

                $this->args[$key] = $val;
            }
        }
    }


    /**
     * Create a new {@link sprintf()}-like formatted HTML string
     *
     * @param string $format
     * @param mixed  ...$args
     *
     * @return static
     */
    public static function create($format, ...$args)
    {
        return new static($format, $args);
    }

    /**
     * Render text to HTML when treated like a string
     *
     * Calls {@link render()} internally in order to render the text to HTML.
     * Exceptions will be automatically caught and returned as HTML string as well using {@link Error::render()}.
     *
     * @return string
     */
    public function __toString()
    {
        try {
            return $this->render();
        } catch (Exception $e) {
            return Error::render($e);
        }
    }

    public function render()
    {
        return vsprintf(
            $this->format->render(),
            $this->args
        );
    }
}