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