Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4abdb3d

Browse filesBrowse files
committed
Refactored DefaultChoiceListFactory
1 parent 1d3ce9b commit 4abdb3d
Copy full SHA for 4abdb3d

File tree

Expand file treeCollapse file tree

3 files changed

+281
-196
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+281
-196
lines changed
+273Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\ChoiceList\Factory;
13+
14+
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
15+
use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView;
16+
use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
17+
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
18+
19+
/**
20+
* A convenient builder for creating {@link ChoiceListView} instances.
21+
*
22+
* @author Valentin Udaltsov <udaltsov.valentin@gmail.com>
23+
*/
24+
final class ChoiceListViewBuilder
25+
{
26+
/**
27+
* @var array|callable|null
28+
*/
29+
private $preferredChoices;
30+
31+
/**
32+
* @var bool|callable|null
33+
*/
34+
private $label;
35+
36+
/**
37+
* @var int|callable
38+
*/
39+
private $index = 0;
40+
41+
/**
42+
* @var callable|null
43+
*/
44+
private $groupBy;
45+
46+
/**
47+
* @var array|callable|null
48+
*/
49+
private $attr;
50+
51+
/**
52+
* @param array|callable|null $preferredChoices
53+
*/
54+
public function setPreferredChoices($preferredChoices): self
55+
{
56+
$this->preferredChoices = $preferredChoices;
57+
58+
return $this;
59+
}
60+
61+
/**
62+
* @param bool|callable|null $preferredChoices
63+
*/
64+
public function setLabel($label): self
65+
{
66+
$this->label = $label;
67+
68+
return $this;
69+
}
70+
71+
public function setIndex(?callable $index): self
72+
{
73+
$this->index = $index ?? 0;
74+
75+
return $this;
76+
}
77+
78+
public function setGroupBy(?callable $groupBy): self
79+
{
80+
$this->groupBy = $groupBy;
81+
82+
return $this;
83+
}
84+
85+
/**
86+
* @param array|callable|null $attr
87+
*/
88+
public function setAttr($attr): self
89+
{
90+
$this->attr = $attr;
91+
92+
return $this;
93+
}
94+
95+
public function buildForList(ChoiceListInterface $list): ChoiceListView
96+
{
97+
$this->resetChoiceIndex();
98+
$view = new ChoiceListView();
99+
100+
if (\is_callable($this->groupBy)) {
101+
$this->addViewsGroupedByCallable(
102+
$view->preferredChoices,
103+
$view->choices,
104+
$list,
105+
$this->groupBy
106+
);
107+
108+
$this->removeEmptyGroupViews($view->preferredChoices);
109+
$this->removeEmptyGroupViews($view->choices);
110+
} else {
111+
$this->addViewsFromStructuredValues(
112+
$view->preferredChoices,
113+
$view->choices,
114+
$list,
115+
$list->getStructuredValues()
116+
);
117+
}
118+
119+
return $view;
120+
}
121+
122+
private function addViewsGroupedByCallable(array &$preferredViews, array &$otherViews, ChoiceListInterface $list, callable $groupBy): void
123+
{
124+
$keys = $list->getOriginalKeys();
125+
126+
foreach ($list->getChoices() as $value => $choice) {
127+
$value = (string) $value;
128+
$key = $keys[$value];
129+
$groupLabel = $groupBy($choice, $key, $value);
130+
131+
if (null === $groupLabel) {
132+
$this->addView($preferredViews, $otherViews, $choice, $key, $value);
133+
134+
continue;
135+
}
136+
137+
$groupLabel = (string) $groupLabel;
138+
139+
if (!isset($preferredViews[$groupLabel])) {
140+
$preferredViews[$groupLabel] = new ChoiceGroupView($groupLabel);
141+
$otherViews[$groupLabel] = new ChoiceGroupView($groupLabel);
142+
}
143+
144+
$this->addView(
145+
$preferredViews[$groupLabel]->choices,
146+
$otherViews[$groupLabel]->choices,
147+
$choice,
148+
$key,
149+
$value
150+
);
151+
}
152+
}
153+
154+
private function addViewsFromStructuredValues(&$preferredViews, &$otherViews, ChoiceListInterface $list, array $values): void
155+
{
156+
$choices = $list->getChoices();
157+
158+
foreach ($values as $key => $value) {
159+
if (null === $value) {
160+
continue;
161+
}
162+
163+
if (!\is_array($value)) {
164+
$this->addView(
165+
$preferredViews,
166+
$otherViews,
167+
$choices[$value],
168+
$key,
169+
$value
170+
);
171+
172+
continue;
173+
}
174+
175+
$preferredViewsForGroup = array();
176+
$otherViewsForGroup = array();
177+
178+
$this->addViewsFromStructuredValues(
179+
$preferredViewsForGroup,
180+
$otherViewsForGroup,
181+
$list,
182+
$value
183+
);
184+
185+
if (\count($preferredViewsForGroup) > 0) {
186+
$preferredViews[$key] = new ChoiceGroupView($key, $preferredViewsForGroup);
187+
}
188+
189+
if (\count($otherViewsForGroup) > 0) {
190+
$otherViews[$key] = new ChoiceGroupView($key, $otherViewsForGroup);
191+
}
192+
}
193+
}
194+
195+
private function addView(array &$preferredViews, array &$otherViews, $choice, $key, $value): void
196+
{
197+
$view = new ChoiceView(
198+
$choice,
199+
$value,
200+
$this->getChoiceLabel($choice, $key, $value),
201+
$this->getChoiceAttr($choice, $key, $value)
202+
);
203+
$index = $this->getChoiceIndex($choice, $key, $value);
204+
205+
if ($this->isChoicePreferred($choice, $key, $value)) {
206+
$preferredViews[$index] = $view;
207+
} else {
208+
$otherViews[$index] = $view;
209+
}
210+
}
211+
212+
private function removeEmptyGroupViews(array &$views): void
213+
{
214+
foreach ($views as $key => $view) {
215+
if ($view instanceof ChoiceGroupView && 0 === \count($view->choices)) {
216+
unset($views[$key]);
217+
}
218+
}
219+
}
220+
221+
private function isChoicePreferred($choice, $key, $value): bool
222+
{
223+
if (empty($this->preferredChoices)) {
224+
return false;
225+
}
226+
227+
if (\is_callable($this->preferredChoices)) {
228+
return ($this->preferredChoices)($choice, $key, $value);
229+
}
230+
231+
return \in_array($choice, $this->preferredChoices, true);
232+
}
233+
234+
private function getChoiceLabel($choice, $key, $value)
235+
{
236+
if (null === $this->label) {
237+
return (string) $key;
238+
}
239+
240+
if (false === $this->label) {
241+
return false;
242+
}
243+
244+
$label = ($this->label)($choice, $key, $value);
245+
246+
return false === $label ? false : (string) $label;
247+
}
248+
249+
private function getChoiceIndex($choice, $key, $value)
250+
{
251+
if (\is_int($this->index)) {
252+
return $this->index++;
253+
}
254+
255+
return ($this->index)($choice, $key, $value);
256+
}
257+
258+
private function resetChoiceIndex(): void
259+
{
260+
if (\is_int($this->index)) {
261+
$this->index = 0;
262+
}
263+
}
264+
265+
private function getChoiceAttr($choice, $key, $value)
266+
{
267+
if (\is_callable($this->attr)) {
268+
return ($this->attr)($choice, $key, $value);
269+
}
270+
271+
return $this->attr[$key] ?? array();
272+
}
273+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.