Passed
Push — master ( 46e4e2...118217 )
by Rustam
02:47
created

Error::render()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 6
nop 0
dl 0
loc 27
ccs 19
cts 19
cp 1
crap 6
rs 9.0777
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field\Part;
6
7
use InvalidArgumentException;
8
use Yiisoft\Form\Field\Base\FormAttributeTrait;
9
use Yiisoft\Html\Html;
10
use Yiisoft\Html\Tag\CustomTag;
11
use Yiisoft\Widget\Widget;
12
13
use function call_user_func;
14
15
/**
16
 * Represent a field validation error (if there are several errors, the first one is used). If field is no validation
17
 * error, field part will be hidden.
18
 */
19
final class Error extends Widget
20
{
21
    use FormAttributeTrait;
22
23
    /**
24
     * @psalm-var non-empty-string
25
     */
26
    private string $tag = 'div';
27
    private array $attributes = [];
28
29
    private bool $encode = true;
30
31
    private ?string $message = null;
32
33
    /**
34
     * @var callable|null
35
     */
36
    private $messageCallback = null;
37
38
    /**
39
     * Set the container tag name for the error.
40
     *
41
     * @param string $tag Container tag name.
42
     */
43 4
    public function tag(string $tag): self
44
    {
45 4
        if ($tag === '') {
46 1
            throw new InvalidArgumentException('Tag name cannot be empty.');
47
        }
48
49 3
        $new = clone $this;
50 3
        $new->tag = $tag;
51 3
        return $new;
52
    }
53
54 4
    public function attributes(array $attributes): self
55
    {
56 4
        $new = clone $this;
57 4
        $new->attributes = $attributes;
58 4
        return $new;
59
    }
60
61 5
    public function addAttributes(array $attributes): self
62
    {
63 5
        $new = clone $this;
64 5
        $new->attributes = array_merge($this->attributes, $attributes);
65 5
        return $new;
66
    }
67
68
    /**
69
     * Set tag ID.
70
     *
71
     * @param string|null $id Tag ID.
72
     */
73 2
    public function id(?string $id): self
74
    {
75 2
        $new = clone $this;
76 2
        $new->attributes['id'] = $id;
77 2
        return $new;
78
    }
79
80
    /**
81
     * Add one or more CSS classes to the tag.
82
     *
83
     * @param string|null ...$class One or many CSS classes.
84
     */
85 10
    public function addClass(?string ...$class): self
86
    {
87 10
        $new = clone $this;
88 10
        Html::addCssClass(
89 10
            $new->attributes,
90 10
            array_filter($class, static fn ($c) => $c !== null),
91 10
        );
92 10
        return $new;
93
    }
94
95
    /**
96
     * Replace tag CSS classes with a new set of classes.
97
     *
98
     * @param string|null ...$class One or many CSS classes.
99
     */
100 9
    public function class(?string ...$class): self
101
    {
102 9
        $new = clone $this;
103 9
        $new->attributes['class'] = array_filter($class, static fn ($c) => $c !== null);
104 9
        return $new;
105
    }
106
107
    /**
108
     * Whether content should be HTML-encoded.
109
     */
110 1
    public function encode(bool $value): self
111
    {
112 1
        $new = clone $this;
113 1
        $new->encode = $value;
114 1
        return $new;
115
    }
116
117
    /**
118
     * Error message to display.
119
     */
120 12
    public function message(?string $value): self
121
    {
122 12
        $new = clone $this;
123 12
        $new->message = $value;
124 12
        return $new;
125
    }
126
127
    /**
128
     * Callback that will be called to obtain an error message.
129
     */
130 3
    public function messageCallback(?callable $value): self
131
    {
132 3
        $new = clone $this;
133 3
        $new->messageCallback = $value;
134 3
        return $new;
135
    }
136
137
    /**
138
     * Generates a tag that contains the first validation error of the specified form attribute.
139
     *
140
     * @return string The generated error tag.
141
     */
142 519
    public function render(): string
143
    {
144 519
        $useModel = $this->hasFormModelAndAttribute();
145
146 519
        $message = $useModel
147 408
            ? $this->message ?? $this->getFirstError()
148 113
            : $this->message;
149
150 519
        if ($message === null) {
151 462
            return '';
152
        }
153
154 57
        if ($this->messageCallback !== null) {
155
            /** @var string $message */
156 3
            $message = call_user_func(
157 3
                $this->messageCallback,
158 3
                $message,
159 3
                $useModel ? $this->getFormModel() : null,
160 3
                $useModel ? $this->formAttribute : null
161 3
            );
162
        }
163
164 57
        return CustomTag::name($this->tag)
165 57
            ->addAttributes($this->attributes)
166 57
            ->content($message)
167 57
            ->encode($this->encode)
168 57
            ->render();
169
    }
170
}
171