Completed
Push — master ( 8a441b...ebc209 )
by Vladimir
04:28
created

SeasonController::showAction()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 112
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 112
rs 8.2857
c 0
b 0
f 0
cc 1
eloc 49
nc 1
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
use Symfony\Component\HttpFoundation\Request;
4
5
class SeasonController extends HTMLController
6
{
7
    /**
8
     * @param Request $request
9
     * @param string  $period    The season's period: winter, spring, summer, fall
10
     * @param int     $year      The season's year
11
     *
12
     * @throws Exception         When a database instance is not configured for the current environment
13
     * @throws NotFoundException When an invalid season is given
14
     *
15
     * @return array
16
     */
17
    public function showAction(Request $request, $period, $year)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
18
    {
19
        $this->parseSeason($period, $year);
20
21
        // Because this query can't be created efficiently using our QueryBuilder, let's do things manually
22
        $db = Database::getInstance();
23
        $seasonQuery = sprintf("
24
            SELECT %s, e.elo_new AS elo FROM players p 
25
              INNER JOIN player_elo e ON e.user_id = p.id 
26
              INNER JOIN (
27
                SELECT
28
                  user_id, 
29
                  MAX(match_id) AS last_match 
30
                FROM
31
                  player_elo 
32
                WHERE
33
                  season_period = ? AND season_year = ?
34
                GROUP BY
35
                  user_id
36
              ) i ON i.user_id = p.id AND i.last_match = e.match_id
37
            WHERE p.status = 'active'
38
            ORDER BY elo DESC, p.username ASC LIMIT 10;
39
        ", Player::getEagerColumns('p'));
40
        $results = $db->query($seasonQuery, [$period, $year]);
41
        $players_w_elos = Player::createFromDatabaseResults($results);
42
43
        $seasonRange = Season::getCurrentSeasonRange($period);
44
        $matchQuery = Match::getQueryBuilder();
45
        $matchQuery
46
            ->active()
47
            ->where('time')->isAfter($seasonRange->getStartOfRange($year), true)
48
            ->where('time')->isBefore($seasonRange->getEndOfRange($year), true)
49
        ;
50
51
        $fmQuery   = clone $matchQuery;
52
        $offiQuery = clone $matchQuery;
53
54
        $fmCount   = $fmQuery->where('type')->equals(Match::FUN)->count();
55
        $offiCount = $offiQuery->where('type')->equals(Match::OFFICIAL)->count();
56
57
        Map::getQueryBuilder()->addToCache();
58
        $mapQuery = '
59
            SELECT
60
              map AS map_id,
61
              COUNT(*) AS match_count
62
            FROM
63
              matches
64
            WHERE
65
              timestamp >= ? AND timestamp <= ? AND map IS NOT NULL
66
            GROUP BY
67
              map
68
            HAVING
69
              match_count > 0
70
            ORDER BY
71
              match_count DESC
72
        ';
73
        $results = $db->query($mapQuery, [
74
            $seasonRange->getStartOfRange($year),
75
            $seasonRange->getEndOfRange($year),
76
        ]);
77
78
        $mapIDs = array_column($results, 'map_id');
79
        $maps = Map::arrayIdToModel($mapIDs);
80
        $mapCount = array_combine($mapIDs, $results);
81
82
        $matchCount = "
83
            SELECT
84
              p.user_id,
85
              SUM(m.match_type = ?) AS match_count
86
            FROM
87
              match_participation p
88
            INNER JOIN
89
              matches m ON m.id = p.match_id
90
            WHERE
91
              m.timestamp >= ? AND m.timestamp < ?
92
            GROUP BY
93
              p.user_id
94
            ORDER BY
95
              match_count DESC
96
            LIMIT 10
97
        ";
98
        $fmResults = $db->query($matchCount, [
99
            'fm',
100
            $seasonRange->getStartOfRange($year),
101
            $seasonRange->getEndOfRange($year),
102
        ]);
103
        $offiResults = $db->query($matchCount, [
104
            'official',
105
            $seasonRange->getStartOfRange($year),
106
            $seasonRange->getEndOfRange($year),
107
        ]);
108
109
        return [
110
            'season'  => ucfirst($period),
111
            'year'    => $year,
112
            'players' => $players_w_elos,
113
            'fmCount' => $fmCount,
114
            'offiCount' => $offiCount,
115
            'maps'    => $maps,
116
            'mapCount' => $mapCount,
117
            'player_matches' => [
118
                'fm' => [
119
                    'players' => Player::arrayIdToModel(array_column($fmResults, 'user_id')),
120
                    'count' => array_column($fmResults, 'match_count'),
121
                ],
122
                'official' => [
123
                    'players' => Player::arrayIdToModel(array_column($offiResults, 'user_id')),
124
                    'count' => array_column($offiResults, 'match_count'),
125
                ],
126
            ],
127
        ];
128
    }
129
130
    /**
131
     * Default to current season or ensure the given season is valid.
132
     *
133
     * @param string $period
134
     * @param int    $year
135
     *
136
     * @throws NotFoundException When an invalid season is found
137
     */
138
    private function parseSeason(&$period, &$year)
139
    {
140
        if (!$this->isValidSeason($period, $year)) {
141
            throw new NotFoundException('The specified season does not seem to exist.');
142
        }
143
144
        if ($period === 'current') {
145
            $period = Season::getCurrentSeason();
146
            $year = TimeDate::now()->year;
147
        }
148
    }
149
150
    /**
151
     * Check that a given season is valid.
152
     *
153
     * @param string $period
154
     * @param int    $seasonYear
155
     *
156
     * @return bool
157
     */
158
    private function isValidSeason($period, $seasonYear)
159
    {
160
        $currentYear = TimeDate::now()->year;
161
162
        // The season's in the future
163
        if ($seasonYear > $currentYear) {
164
            return false;
165
        }
166
167
        // If the year's the same, we need to make sure the season's not in the future; e.g. Fall 2017 shouldn't be
168
        // valid when it's only July 2017
169
        if ($seasonYear == $currentYear &&
170
            Season::toInt($period) > Season::toInt(Season::getCurrentSeason())
171
        ) {
172
            return false;
173
        }
174
175
        return true;
176
    }
177
}
178