1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file contains a form creator for Matches |
4
|
|
|
* |
5
|
|
|
* @license https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3 |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace BZIon\Form\Creator; |
9
|
|
|
|
10
|
|
|
use BZIon\Form\Type\DatetimeWithTimezoneType; |
11
|
|
|
use BZIon\Form\Type\MatchTeamType; |
12
|
|
|
use BZIon\Form\Type\ModelType; |
13
|
|
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; |
14
|
|
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType; |
15
|
|
|
use Symfony\Component\Form\FormError; |
16
|
|
|
use Symfony\Component\Form\FormEvent; |
17
|
|
|
use Symfony\Component\Form\FormEvents; |
18
|
|
|
use Symfony\Component\Form\FormInterface; |
19
|
|
|
use Symfony\Component\Validator\Constraints\LessThan; |
20
|
|
|
use Symfony\Component\Validator\Constraints\NotBlank; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Form creator for matches |
24
|
|
|
* |
25
|
1 |
|
* @property \Match $editing |
26
|
|
|
*/ |
27
|
1 |
|
class MatchFormCreator extends ModelFormCreator |
28
|
1 |
|
{ |
29
|
1 |
|
/** |
30
|
|
|
* {@inheritdoc} |
31
|
|
|
*/ |
32
|
|
|
protected function build($builder) |
33
|
1 |
|
{ |
34
|
1 |
|
$durations = \Service::getParameter('bzion.league.duration'); |
35
|
|
|
foreach ($durations as $duration => &$value) { |
36
|
1 |
|
$durations[$duration] = $duration; |
37
|
1 |
|
} |
38
|
|
|
|
39
|
1 |
|
return $builder |
40
|
1 |
|
->add('first_team', new MatchTeamType(), [ |
41
|
1 |
|
'disableTeam' => $this->isEdit() && $this->editing->isOfficial(), |
42
|
|
|
]) |
43
|
|
|
->add('second_team', new MatchTeamType(), [ |
44
|
1 |
|
'disableTeam' => $this->isEdit() && $this->editing->isOfficial(), |
45
|
1 |
|
]) |
46
|
|
|
->add('duration', ChoiceType::class, array( |
47
|
|
|
'choices' => $durations, |
48
|
1 |
|
'constraints' => new NotBlank(), |
49
|
|
|
'expanded' => true, |
50
|
1 |
|
)) |
51
|
1 |
|
->add('server', new ModelType('Server'), [ |
52
|
1 |
|
'constraints' => new NotBlank(), |
53
|
1 |
|
'choice_label' => function ($value) { |
54
|
|
|
$server = \Server::get($value); |
55
|
|
|
return $server->isValid() ? $server->getAddress() : ''; |
56
|
1 |
|
}, |
57
|
|
|
]) |
58
|
1 |
|
->add('time', new DatetimeWithTimezoneType(), array( |
59
|
1 |
|
'constraints' => array( |
60
|
|
|
new NotBlank(), |
61
|
1 |
|
new LessThan(array( |
62
|
1 |
|
'value' => \TimeDate::now()->addMinutes(10), |
63
|
|
|
'message' => 'The timestamp of the match must not be in the future' |
64
|
1 |
|
)) |
65
|
1 |
|
), |
66
|
|
|
'data' => ($this->isEdit()) |
67
|
|
|
? $this->editing->getTimestamp()->setTimezone(\Controller::getMe()->getTimezone()) |
68
|
|
|
: \TimeDate::now(\Controller::getMe()->getTimezone()), |
69
|
|
|
'with_seconds' => $this->isEdit(), |
70
|
1 |
|
)) |
71
|
1 |
|
->add('map', new ModelType('Map'), array( |
72
|
|
|
'required' => true, |
73
|
1 |
|
)) |
74
|
|
|
->add('type', ChoiceType::class, array( |
75
|
|
|
'choices' => array( |
76
|
|
|
\Match::OFFICIAL => 'Official', |
77
|
|
|
\Match::FUN => 'Fun match', |
78
|
|
|
\Match::SPECIAL => 'Special event match', |
79
|
|
|
), |
80
|
|
|
'disabled' => $this->editing && $this->editing->isOfficial(), |
81
|
|
|
'label' => 'Match Type', |
82
|
|
|
)) |
83
|
|
|
->add('enter', SubmitType::class, [ |
84
|
|
|
'attr' => [ |
85
|
|
|
'class' => 'c-button--blue pattern pattern--downward-stripes', |
86
|
|
|
], |
87
|
|
|
]) |
88
|
|
|
->addEventListener(FormEvents::POST_SUBMIT, [$this, 'checkUniqueRoster']) |
89
|
|
|
; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Form event handler that makes sure the participants are not on both teams. |
94
|
|
|
* |
95
|
|
|
* @param FormEvent $event |
96
|
|
|
*/ |
97
|
|
|
public function checkUniqueRoster(FormEvent $event) |
98
|
|
|
{ |
99
|
|
|
$playersA = $event->getForm()->get('first_team')->get('participants')->getData(); |
100
|
|
|
$playersB = $event->getForm()->get('second_team')->get('participants')->getData(); |
101
|
|
|
|
102
|
|
|
$duplicates = array_intersect($playersA, $playersB); |
103
|
|
|
|
104
|
|
|
if (!empty($duplicates)) { |
105
|
|
|
$callsigns = array_map(function ($player) { return $player->getUsername(); }, $duplicates); |
106
|
|
|
|
107
|
|
|
$event->getForm()->addError(new FormError('Players ' . implode(', ', $callsigns) . ' cannot belong to both teams.')); |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* {@inheritdoc} |
113
|
|
|
* |
114
|
|
|
* @param \Match $match |
115
|
|
|
*/ |
116
|
|
|
public function fill($form, $match) |
117
|
|
|
{ |
118
|
|
|
$form->get('first_team')->setData([ |
119
|
|
|
'team' => $match->getTeamA(), |
120
|
|
|
'participants' => $match->getTeamAPlayers(), |
121
|
|
|
'score' => $match->getTeamAPoints() |
122
|
|
|
]); |
123
|
|
|
$form->get('second_team')->setData([ |
124
|
|
|
'team' => $match->getTeamB(), |
125
|
|
|
'participants' => $match->getTeamBPlayers(), |
126
|
|
|
'score' => $match->getTeamBPoints() |
127
|
|
|
]); |
128
|
|
|
|
129
|
|
|
$form->get('duration')->setData($match->getDuration()); |
130
|
|
|
$form->get('server')->setData($match->getServer()); |
131
|
|
|
$form->get('time')->setData($match->getTimestamp()); |
132
|
|
|
$form->get('map')->setData($match->getMap()); |
133
|
|
|
$form->get('type')->setData($match->getMatchType()); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* {@inheritdoc} |
138
|
|
|
* |
139
|
|
|
* @param \Match $match |
140
|
|
|
*/ |
141
|
|
|
public function update($form, $match) |
142
|
|
|
{ |
143
|
|
|
if (($match->getDuration() != $form->get('duration')->getData()) |
144
|
|
|
|| $match->getTimestamp()->ne($form->get('time')->getData())) { |
145
|
|
|
// The timestamp of the match was changed, we might need to |
146
|
|
|
// recalculate its ELO |
147
|
|
|
$this->controller->recalculateNeeded = true; |
|
|
|
|
148
|
1 |
|
} |
149
|
|
|
|
150
|
1 |
|
$firstTeam = $form->get('first_team'); |
151
|
1 |
|
$secondTeam = $form->get('second_team'); |
152
|
|
|
|
153
|
1 |
|
if (!$match->isOfficial()) { |
154
|
1 |
|
$match->setTeamColors( |
155
|
|
|
$firstTeam->get('team')->getData(), |
156
|
1 |
|
$secondTeam->get('team')->getData() |
157
|
1 |
|
); |
158
|
|
|
} |
159
|
1 |
|
|
160
|
|
|
$match->setTeamPlayers( |
161
|
1 |
|
$this->getPlayerList($firstTeam), |
162
|
1 |
|
$this->getPlayerList($secondTeam) |
163
|
1 |
|
); |
164
|
1 |
|
|
165
|
1 |
|
$match->setTeamPoints( |
166
|
1 |
|
$firstTeam->get('score')->getData(), |
167
|
1 |
|
$secondTeam->get('score')->getData() |
168
|
1 |
|
); |
169
|
1 |
|
|
170
|
1 |
|
$match |
171
|
1 |
|
->setDuration($form->get('duration')->getData()) |
172
|
1 |
|
->setServer($form->get('server')->getData()->getId()) |
173
|
1 |
|
->setTimestamp($form->get('time')->getData()) |
174
|
1 |
|
->setMap($form->get('map')->getData()->getId()); |
175
|
1 |
|
|
176
|
1 |
|
if (!$match->isEloCorrect()) { |
177
|
|
|
$this->controller->recalculateNeeded = true; |
178
|
|
|
} |
179
|
1 |
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* {@inheritdoc} |
183
|
|
|
*/ |
184
|
|
|
public function enter($form) |
185
|
|
|
{ |
186
|
|
|
$firstTeam = $form->get('first_team'); |
187
|
|
|
$secondTeam = $form->get('second_team'); |
188
|
1 |
|
|
189
|
|
|
$firstId = $firstTeam->get('team')->getData()->getId(); |
190
|
1 |
|
$secondId = $secondTeam->get('team')->getData()->getId(); |
191
|
|
|
|
192
|
|
|
$a_color = \ColorTeam::isValidTeamColor($firstId) ? $firstId : null; |
193
|
|
|
$b_color = \ColorTeam::isValidTeamColor($secondId) ? $secondId : null; |
194
|
|
|
|
195
|
|
|
$official = ($form->get('type')->getData() === \Match::OFFICIAL); |
196
|
|
|
|
197
|
|
|
/** @var \Server $server */ |
198
|
|
|
$server = $form->get('server')->getData(); |
199
|
|
|
|
200
|
1 |
|
$match = \Match::enterMatch( |
201
|
1 |
|
$official ? $firstId : null, |
202
|
1 |
|
$official ? $secondId : null, |
203
|
|
|
$firstTeam->get('score')->getData(), |
204
|
|
|
$secondTeam->get('score')->getData(), |
205
|
|
|
$form->get('duration')->getData(), |
206
|
|
|
$this->me->getId(), |
207
|
|
|
$form->get('time')->getData(), |
208
|
|
|
$this->getPlayerList($firstTeam), |
209
|
|
|
$this->getPlayerList($secondTeam), |
210
|
|
|
$server->getAddress(), |
211
|
|
|
null, |
212
|
|
|
$form->get('map')->getData()->getId(), |
213
|
|
|
$form->get('type')->getData(), |
214
|
|
|
$a_color, |
215
|
|
|
$b_color |
216
|
|
|
); |
217
|
|
|
|
218
|
|
|
if ($server->isValid()) { |
219
|
|
|
$match->setServer($server->getId()); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
return $match; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Get the player list of a team |
227
|
|
|
* |
228
|
|
|
* @param FormInterface $team A MatchTeamType form |
229
|
|
|
* @return array |
230
|
|
|
*/ |
231
|
|
|
private function getPlayerList(FormInterface $team) |
232
|
|
|
{ |
233
|
|
|
return array_map($this->getModelToID(), $team->get('participants')->getData()); |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* Get a function which converts models to their IDs |
238
|
|
|
* |
239
|
|
|
* Useful to store the match players into the database |
240
|
|
|
*/ |
241
|
|
|
private static function getModelToID() |
242
|
|
|
{ |
243
|
|
|
return function ($model) { |
244
|
|
|
return $model->getId(); |
245
|
|
|
}; |
246
|
|
|
} |
247
|
|
|
} |
248
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.