Completed
Push — master ( f07db2...518be4 )
by Vladimir
02:55
created

MatchFormCreator   B

Complexity

Total Complexity 23

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 17

Test Coverage

Coverage 59.38%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 23
c 1
b 0
f 0
lcom 2
cbo 17
dl 0
loc 217
ccs 57
cts 96
cp 0.5938
rs 7.8571

7 Methods

Rating   Name   Duplication   Size   Complexity  
B build() 0 55 7
A checkUniqueRoster() 0 13 2
A fill() 0 19 1
B update() 0 39 5
B enter() 0 40 6
A getPlayerList() 0 4 1
A getModelToID() 0 6 1
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
            ->addEventListener(FormEvents::POST_SUBMIT, [$this, 'checkUniqueRoster'])
85
        ;
86
    }
87
88
    /**
89
     * Form event handler that makes sure the participants are not on both teams.
90
     *
91
     * @param FormEvent $event
92
     */
93
    public function checkUniqueRoster(FormEvent $event)
94
    {
95
        $playersA = $event->getForm()->get('first_team')->get('participants')->getData();
96
        $playersB = $event->getForm()->get('second_team')->get('participants')->getData();
97
98
        $duplicates = array_intersect($playersA, $playersB);
99
100
        if (!empty($duplicates)) {
101
            $callsigns = array_map(function ($player) { return $player->getUsername(); }, $duplicates);
102
103
            $event->getForm()->addError(new FormError('Players ' . implode(', ', $callsigns) . ' cannot belong to both teams.'));
104
        }
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     *
110
     * @param \Match $match
111
     */
112
    public function fill($form, $match)
113
    {
114
        $form->get('first_team')->setData([
115
            'team'         => $match->getTeamA(),
116
            'participants' => $match->getTeamAPlayers(),
117
            'score'        => $match->getTeamAPoints()
118
        ]);
119
        $form->get('second_team')->setData([
120
            'team'         => $match->getTeamB(),
121
            'participants' => $match->getTeamBPlayers(),
122
            'score'        => $match->getTeamBPoints()
123
        ]);
124
125
        $form->get('duration')->setData($match->getDuration());
126
        $form->get('server')->setData($match->getServer());
127
        $form->get('time')->setData($match->getTimestamp());
128
        $form->get('map')->setData($match->getMap());
129
        $form->get('type')->setData($match->getMatchType());
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     *
135
     * @param \Match $match
136
     */
137
    public function update($form, $match)
138
    {
139
        if (($match->getDuration() != $form->get('duration')->getData())
140
            || $match->getTimestamp()->ne($form->get('time')->getData())) {
141
            // The timestamp of the match was changed, we might need to
142
            // recalculate its ELO
143
            $this->controller->recalculateNeeded = true;
0 ignored issues
show
Bug introduced by
The property recalculateNeeded does not seem to exist in Controller.

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.

Loading history...
144
        }
145
146
        $firstTeam  = $form->get('first_team');
147
        $secondTeam = $form->get('second_team');
148 1
149
        if (!$match->isOfficial()) {
150 1
            $match->setTeamColors(
151 1
                $firstTeam->get('team')->getData(),
152
                $secondTeam->get('team')->getData()
153 1
            );
154 1
        }
155
156 1
        $match->setTeamPlayers(
157 1
            $this->getPlayerList($firstTeam),
158
            $this->getPlayerList($secondTeam)
159 1
        );
160
161 1
        $match->setTeamPoints(
162 1
            $firstTeam->get('score')->getData(),
163 1
            $secondTeam->get('score')->getData()
164 1
        );
165 1
166 1
        $match
167 1
            ->setDuration($form->get('duration')->getData())
168 1
            ->setServer($form->get('server')->getData()->getId())
169 1
            ->setTimestamp($form->get('time')->getData())
170 1
            ->setMap($form->get('map')->getData()->getId());
171 1
172 1
        if (!$match->isEloCorrect()) {
173 1
            $this->controller->recalculateNeeded = true;
174 1
        }
175 1
    }
176 1
177
    /**
178
     * {@inheritdoc}
179 1
     */
180
    public function enter($form)
181
    {
182
        $firstTeam  = $form->get('first_team');
183
        $secondTeam = $form->get('second_team');
184
185
        $firstId = $firstTeam->get('team')->getData()->getId();
186
        $secondId = $secondTeam->get('team')->getData()->getId();
187
188 1
        $a_color = \ColorTeam::isValidTeamColor($firstId) ? $firstId : null;
189
        $b_color = \ColorTeam::isValidTeamColor($secondId) ? $secondId : null;
190 1
191
        $official = ($form->get('type')->getData() === \Match::OFFICIAL);
192
193
        /** @var \Server $server */
194
        $server = $form->get('server')->getData();
195
196
        $match = \Match::enterMatch(
197
            $official ? $firstId : null,
198
            $official ? $secondId : null,
199
            $firstTeam->get('score')->getData(),
200 1
            $secondTeam->get('score')->getData(),
201 1
            $form->get('duration')->getData(),
202 1
            $this->me->getId(),
203
            $form->get('time')->getData(),
204
            $this->getPlayerList($firstTeam),
205
            $this->getPlayerList($secondTeam),
206
            $server->getAddress(),
207
            null,
208
            $form->get('map')->getData()->getId(),
209
            $form->get('type')->getData(),
210
            $a_color,
211
            $b_color
212
        );
213
214
        if ($server->isValid()) {
215
            $match->setServer($server->getId());
216
        }
217
218
        return $match;
219
    }
220
221
    /**
222
     * Get the player list of a team
223
     *
224
     * @param FormInterface $team A MatchTeamType form
225
     * @return array
226
     */
227
    private function getPlayerList(FormInterface $team)
228
    {
229
        return array_map($this->getModelToID(),  $team->get('participants')->getData());
230
    }
231
232
    /**
233
     * Get a function which converts models to their IDs
234
     *
235
     * Useful to store the match players into the database
236
     */
237
    private static function getModelToID()
238
    {
239
        return function ($model) {
240
            return $model->getId();
241
        };
242
    }
243
}
244