MatchFormCreator   B
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 221
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 221
rs 7.8571
ccs 57
cts 96
cp 0.5938

7 Methods

Rating   Name   Duplication   Size   Complexity  
B build() 0 59 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
                '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;
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...
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