Passed
Pull Request — master (#191)
by Wilmer
02:51
created

Error::run()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 12
nc 8
nop 0
dl 0
loc 20
ccs 13
cts 13
cp 1
crap 6
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget\FieldPart;
6
7
use Yiisoft\Form\Exception\AttributeNotSetException;
8
use Yiisoft\Form\Exception\FormModelNotSetException;
9
use Yiisoft\Form\FormModelInterface;
10
use Yiisoft\Form\Helper\HtmlFormErrors;
11
use Yiisoft\Html\Tag\CustomTag;
12
use Yiisoft\Widget\Widget;
13
14
/**
15
 * The Error widget displays an error message.
16
 */
17
final class Error extends Widget
18
{
19
    private string $attribute = '';
20
    private array $attributes = [];
21
    private bool $encode = false;
22
    private string $message = '';
23
    private array $messageCallback = [];
24
    private string $tag = 'div';
25
    private ?FormModelInterface $formModel = null;
26
27
    /**
28
     * The HTML attributes. The following special options are recognized.
29
     *
30
     * @param array $values Attribute values indexed by attribute names.
31
     *
32
     * @return static
33
     *
34
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
35
     */
36 358
    public function attributes(array $values): self
37
    {
38 358
        $new = clone $this;
39 358
        $new->attributes = $values;
40 358
        return $new;
41
    }
42
43
    /**
44
     * Whether content should be HTML-encoded.
45
     *
46
     * @param bool $value
47
     *
48
     * @return static
49
     */
50 359
    public function encode(bool $value): self
51
    {
52 359
        $new = clone $this;
53 359
        $new->encode = $value;
54 359
        return $new;
55
    }
56
57
    /**
58
     * @return static
59
     */
60 364
    public function for(FormModelInterface $formModel, string $attribute): self
61
    {
62 364
        $new = clone $this;
63 364
        $new->formModel = $formModel;
64 364
        $new->attribute = $attribute;
65 364
        return $new;
66
    }
67
68
    /**
69
     * Error message to display.
70
     *
71
     * @return static
72
     */
73 359
    public function message(string $value): self
74
    {
75 359
        $new = clone $this;
76 359
        $new->message = $value;
77 359
        return $new;
78
    }
79
80
    /**
81
     * Callback that will be called to obtain an error message.
82
     *
83
     * The signature of the callback must be:
84
     *
85
     * ```php
86
     * [$FormModel, function()]
87
     * ```
88
     *
89
     * @param array $value
90
     *
91
     * @return static
92
     */
93 360
    public function messageCallback(array $value): self
94
    {
95 360
        $new = clone $this;
96 360
        $new->messageCallback = $value;
97 360
        return $new;
98
    }
99
100
    /**
101
     * The tag name of the container element.
102
     *
103
     * Empty to render error messages without container {@see Html::tag()}.
104
     *
105
     * @param string $value
106
     *
107
     * @return static
108
     */
109 359
    public function tag(string $value): self
110
    {
111 359
        $new = clone $this;
112 359
        $new->tag = $value;
113 359
        return $new;
114
    }
115
116
    /**
117
     * Generates a tag that contains the first validation error of the specified form attribute.
118
     *
119
     * @return string the generated label tag
120
     */
121 363
    protected function run(): string
122
    {
123 363
        $error = HtmlFormErrors::getFirstError($this->getFormModel(), $this->getAttribute());
124
125 362
        if ($error !== '' && $this->message !== '') {
126 3
            $error = $this->message;
127
        }
128
129 362
        if ($error !== '' && $this->messageCallback !== []) {
130
            /** @var string */
131 4
            $error = call_user_func($this->messageCallback, $this->getFormModel(), $this->getAttribute());
132
        }
133
134 362
        return match ($this->tag !== '' && $error !== '') {
135 13
            true => CustomTag::name($this->tag)
136 13
                ->attributes($this->attributes)
137 13
                ->content($error)
138 13
                ->encode($this->encode)
139 13
                ->render(),
140 362
            false => $error,
141
        };
142
    }
143
144 363
    private function getAttribute(): string
145
    {
146 363
        return match (empty($this->attribute)) {
147 1
            true => throw new AttributeNotSetException(),
148 362
            false => $this->attribute,
149
        };
150
    }
151
152
    /**
153
     * Return FormModelInterface object.
154
     *
155
     * @return FormModelInterface
156
     */
157 364
    private function getFormModel(): FormModelInterface
158
    {
159 364
        return match (empty($this->formModel)) {
160 1
            true => throw new FormModelNotSetException(),
161 363
            false => $this->formModel,
162
        };
163
    }
164
}
165