Completed
Push — feature/player-elo ( c8bc0c...592f6a )
by Vladimir
03:20
created

PlayerController   B

Complexity

Total Complexity 28

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 16

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 28
lcom 1
cbo 16
dl 0
loc 167
ccs 0
cts 82
cp 0
rs 8.4614
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
C showAction() 0 46 7
A editAction() 0 13 2
F listAction() 0 80 17
A handleAdminNotesForm() 0 13 2
1
<?php
2
3
use BZIon\Form\Creator\PlayerAdminNotesFormCreator as FormCreator;
4
use Carbon\Carbon;
5
use Symfony\Component\Form\Form;
6
use Symfony\Component\HttpFoundation\Request;
7
8
class PlayerController extends JSONController
9
{
10
    private $creator;
11
12
    public function showAction(Player $player, Player $me, Request $request)
13
    {
14
        $formView = null;
15
16
        if ($me->hasPermission(Permission::VIEW_VISITOR_LOG)) {
17
            $this->creator = new FormCreator($player);
18
            $form = $this->creator->create()->handleRequest($request);
19
20
            if ($form->isValid()) {
21
                $form = $this->handleAdminNotesForm($form, $player, $me);
0 ignored issues
show
Compatibility introduced by
$form of type object<Symfony\Component\Form\FormInterface> is not a sub-type of object<Symfony\Component\Form\Form>. It seems like you assume a concrete implementation of the interface Symfony\Component\Form\FormInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
22
            }
23
24
            $formView = $form->createView();
25
        }
26
27
        $periods = [];
28
        $season = Season::getCurrentSeasonRange();
29
        $periodLength = round($season->getEndOfRange()->diffInDays($season->getStartOfRange()) / 30);
30
        $seasonStart = $season->getStartOfRange();
31
32
        for ($i = 0; $i < $periodLength; $i++) {
33
            $periods[] = $seasonStart->firstOfMonth()->copy();
34
            $periods[] = $seasonStart->day(15)->copy();
35
            $periods[] = $seasonStart->lastOfMonth()->copy();
36
37
            $seasonStart->addMonth();
38
        }
39
40
        $currentPeriod = new ArrayIterator($periods);
41
        $playerEloSeason = $player->getEloSeasonHistory();
42
        $seasonSummary = [];
43
44
        foreach ($playerEloSeason as $elo) {
45
            if ($elo['month'] > $currentPeriod->current()->month || $elo['day'] > $currentPeriod->current()->day) {
46
                $currentPeriod->next();
47
            }
48
49
            $seasonSummary[$currentPeriod->current()->format('M d')] = $elo['elo'];
50
        }
51
52
        return array(
53
            'player'         => $player,
54
            'seasonSummary'  => $seasonSummary,
55
            'adminNotesForm' => $formView,
56
        );
57
    }
58
59
    public function editAction(Player $player, Player $me)
60
    {
61
        if (!$me->canEdit($player)) {
62
            throw new ForbiddenException("You are not allowed to edit other players");
63
        }
64
65
        $params = array(
66
            'me'   => $player,
67
            'self' => false,
68
        );
69
70
        return $this->forward('edit', $params, 'Profile');
71
    }
72
73
    public function listAction(Request $request, Player $me, Team $team = null)
74
    {
75
        $query = Player::getQueryBuilder();
76
77
        // Load all countries into the cache so they are ready for later
78
        Country::getQueryBuilder()->addToCache();
79
80
        if ($team) {
81
            $query->where('team')->is($team);
82
        } else {
83
            // Add all teams to the cache
84
            $this->getQueryBuilder('Team')
85
                ->where('members')->greaterThan(0)
86
                ->addToCache();
87
        }
88
89
        if ($request->query->has('exceptMe')) {
90
            $query->except($me);
91
        }
92
93
        $groupBy = $request->query->get('groupBy');
94
        $sortBy = $request->query->get('sortBy');
95
        $sortOrder = $request->query->get('sortOrder');
96
97
        $query
98
            ->active()
99
            ->withMatchActivity()
100
            ->sortBy('name')
101
        ;
102
103
        if (!$request->query->get('showAll')) {
104
            $query->having('activity')->greaterThan(0);
105
        }
106
107
        if ($sortBy || $sortOrder) {
108
            $sortBy = $sortBy ? $sortBy : 'callsign';
109
            $sortOrder = $sortOrder ? $sortOrder : 'ASC';
110
111
            if ($sortBy === 'activity') {
112
                $query->sortBy($sortBy);
113
            }
114
115
            if ($sortOrder == 'DESC') {
116
                $query->reverse();
117
            }
118
        }
119
120
        $players = $query->getModels($fast = true);
121
122
        if ($groupBy) {
123
            $grouped = [];
124
125
            /** @var Player $player */
126
            foreach ($players as $player) {
127
                $key = '';
128
129
                if ($groupBy == 'country') {
130
                    $key = $player->getCountry()->getName();
131
                } elseif ($groupBy == 'team') {
132
                    $key = $player->getTeam()->getEscapedName();
133
134
                    if ($key == '<em>None</em>') {
135
                        $key = ' ';
136
                    }
137
                } elseif ($groupBy == 'activity') {
138
                    $key = ($player->getMatchActivity() > 0.0) ? 'Active' : 'Inactive';
139
                }
140
141
                $grouped[$key][] = $player;
142
            }
143
144
            ksort($grouped);
145
            $players = $grouped;
146
        }
147
148
        return array(
149
            'grouped' => ($groupBy !== null),
150
            'players' => $players,
151
        );
152
    }
153
154
    /**
155
     * Handle the admin notes form
156
     * @param  Form   $form   The form
157
     * @param  Player $player The player in question
158
     * @param  Player $me     The currently logged in player
159
     * @return Form   The updated form
160
     */
161
    private function handleAdminNotesForm($form, $player, $me)
162
    {
163
        $notes = $form->get('notes')->getData();
164
        if ($form->get('save_and_sign')->isClicked()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Form\FormInterface as the method isClicked() does only exist in the following implementations of said interface: Symfony\Component\Form\SubmitButton.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
165
            $notes .= ' — ' . $me->getUsername() . ' on ' . TimeDate::now()->toRFC2822String();
166
        }
167
168
        $player->setAdminNotes($notes);
169
        $this->getFlashBag()->add('success', "The admin notes for {$player->getUsername()} have been updated");
170
171
        // Reset the form so that the user sees the updated admin notes
172
        return $this->creator->create();
173
    }
174
}
175