Passed
Pull Request — master (#160)
by Wilmer
03:13
created

Error::run()   B

Complexity

Conditions 7
Paths 16

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

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