Passed
Pull Request — master (#192)
by Sergei
13:59
created

ErrorSummary::formModel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field;
6
7
use InvalidArgumentException;
8
use Yiisoft\Form\Field\Base\BaseField;
9
use Yiisoft\Form\FormModelInterface;
10
use Yiisoft\Form\Helper\HtmlFormErrors;
11
use Yiisoft\Html\Html;
12
13
/**
14
 * Displays a summary of the form validation errors. If there is no validation error, field will be hidden.
15
 */
16
final class ErrorSummary extends BaseField
17
{
18
    private ?FormModelInterface $formModel = null;
19
    private bool $encode = true;
20
21
    private bool $showAllErrors = false;
22
    private array $onlyAttributes = [];
23
24
    private string $footer = '';
25
    private array $footerAttributes = [];
26
    private string $header = 'Please fix the following errors:';
27
    private array $headerAttributes = [];
28
29 10
    public function formModel(FormModelInterface $formModel): self
30
    {
31 10
        $new = clone $this;
32 10
        $new->formModel = $formModel;
33 10
        return $new;
34
    }
35
36
    /**
37
     * Whether error content should be HTML-encoded.
38
     */
39 2
    public function encode(bool $value): self
40
    {
41 2
        $new = clone $this;
42 2
        $new->encode = $value;
43 2
        return $new;
44
    }
45
46
    /**
47
     * Whether to show all errors.
48
     */
49 2
    public function showAllErrors(bool $value = true): self
50
    {
51 2
        $new = clone $this;
52 2
        $new->showAllErrors = $value;
53 2
        return $new;
54
    }
55
56
    /**
57
     * Specific attributes to be filtered out when rendering the error summary.
58
     *
59
     * @param array $names The attribute names to be included in error summary.
60
     */
61 8
    public function onlyAttributes(string ...$names): self
62
    {
63 8
        $new = clone $this;
64 8
        $new->onlyAttributes = $names;
65 8
        return $new;
66
    }
67
68
    /**
69
     * Set the footer text for the error summary
70
     *
71
     * @param string $value
72
     *
73
     * @return self
74
     */
75 2
    public function footer(string $value): self
76
    {
77 2
        $new = clone $this;
78 2
        $new->footer = $value;
79 2
        return $new;
80
    }
81
82
    /**
83
     * Set footer attributes for the error summary.
84
     *
85
     * @param array $values Attribute values indexed by attribute names.
86
     *
87
     * @return self
88
     *
89
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
90
     */
91 2
    public function footerAttributes(array $values): self
92
    {
93 2
        $new = clone $this;
94 2
        $new->footerAttributes = $values;
95 2
        return $new;
96
    }
97
98
    /**
99
     * Set the header text for the error summary
100
     *
101
     * @param string $value
102
     *
103
     * @return self
104
     */
105 2
    public function header(string $value): self
106
    {
107 2
        $new = clone $this;
108 2
        $new->header = $value;
109 2
        return $new;
110
    }
111
112
    /**
113
     * Set header attributes for the error summary.
114
     *
115
     * @param array $values Attribute values indexed by attribute names.
116
     *
117
     * @return self
118
     *
119
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
120
     */
121 2
    public function headerAttributes(array $values): self
122
    {
123 2
        $new = clone $this;
124 2
        $new->headerAttributes = $values;
125 2
        return $new;
126
    }
127
128 10
    protected function generateContent(): ?string
129
    {
130 10
        $messages = $this->collectErrors();
131 9
        if (empty($messages)) {
132 1
            return null;
133
        }
134
135 8
        $content = [];
136
137 8
        if ($this->header !== '') {
138 8
            $content[] = Html::p($this->header, $this->headerAttributes)->render();
139
        }
140
141 8
        $content[] = Html::ul()->strings($messages, [], $this->encode)->render();
142
143 8
        if ($this->footer !== '') {
144 1
            $content[] = Html::p($this->footer, $this->footerAttributes)->render();
145
        }
146
147 8
        return implode("\n", $content);
148
    }
149
150
    /**
151
     * Return array of the validation errors.
152
     *
153
     * @return string[] Array of the validation errors.
154
     */
155 10
    private function collectErrors(): array
156
    {
157 10
        if ($this->formModel === null) {
158 1
            throw new InvalidArgumentException('Form model is not set.');
159
        }
160
161 9
        $errors = HtmlFormErrors::getErrorSummaryFirstErrors($this->formModel);
162
163 9
        if ($this->showAllErrors) {
164 1
            $errors = HtmlFormErrors::getErrorSummary($this->formModel, $this->onlyAttributes);
165 8
        } elseif ($this->onlyAttributes !== []) {
166 6
            $errors = array_intersect_key($errors, array_flip($this->onlyAttributes));
167
        }
168
169
        /**
170
         * If there are the same error messages for different attributes, array_unique will leave gaps between
171
         * sequential keys. Applying array_values to reorder array keys.
172
         *
173
         * @var string[]
174
         */
175 9
        return array_values(array_unique($errors));
176
    }
177
}
178