Completed
Push — master ( 7aab3a...2b8a1f )
by Vladimir
18:21 queued 01:15
created

MatchesTableRestructure::up()   C

Complexity

Conditions 9
Paths 4

Size

Total Lines 94
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 94
rs 5.0297
c 0
b 0
f 0
cc 9
eloc 65
nc 4
nop 0

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 Phinx\Migration\AbstractMigration;
4
5
class MatchesTableRestructure extends AbstractMigration
6
{
7
    //
8
    // This table will be used to store participation of players in matches. This is to take the place of a comma
9
    // separated column in the `matches` table for faster JOIN operations versus string operations.
10
    //
11
12
    public function up()
13
    {
14
        $playerParticipationTable = $this->table('match_participation', [
15
            'id' => false,
16
            'primary_key' => ['match_id', 'user_id']
17
        ]);
18
        $playerParticipationTable
19
            ->addColumn('match_id', 'integer', [
20
                'signed' => false,
21
                'limit' => 10,
22
                'null' => false,
23
                'comment' => 'The ID of the match this player participated in',
24
            ])
25
            ->addColumn('user_id', 'integer', [
26
                'signed' => false,
27
                'limit' => 10,
28
                'null' => false,
29
                'comment' => 'The ID of the player who participated in this match',
30
            ])
31
            ->addColumn('team_id', 'integer', [
32
                'signed' => false,
33
                'limit' => 10,
34
                'null' => true,
35
                'comment' => 'The ID of the team this player played for at the time of this match'
36
            ])
37
            ->addColumn('callsign', 'string', [
38
                'null' => true,
39
                'comment' => 'The callsign used by the player during this match.',
40
            ])
41
            ->addColumn('ip_address', 'string', [
42
                'limit' => 46,
43
                'null' => true,
44
                'comment' => 'The IP address used by the player in this match',
45
            ])
46
            // Integer operations in SQL are faster than strings; so for team loyalty, we can simplify it to 0 or 1
47
            ->addColumn('team_loyalty', 'integer', [
48
                'after' => 'callsign',
49
                'limit' => 1,
50
                'null' => false,
51
                'comment' => 'The team color this player played for: 0 will be for "TEAM A" and 1 will be for "TEAM B"'
52
            ])
53
            ->addForeignKey('match_id', 'matches', 'id', ['delete' => 'CASCADE'])
54
            ->addForeignKey('user_id', 'players', 'id', ['delete' => 'CASCADE'])
55
            ->addForeignKey('team_id', 'teams', 'id', ['delete' => 'SET_NULL'])
56
            ->create()
57
        ;
58
59
        $statement = $this->query("SELECT * FROM matches WHERE (team_a_players IS NOT NULL AND team_a_players != '') OR (team_b_players IS NOT NULL AND team_b_players != '')");
60
        $matches = $statement->fetchAll();
0 ignored issues
show
Bug introduced by
The method fetchAll cannot be called on $statement (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
61
        $insertData = [];
62
63
        foreach ($matches as $match) {
64
            $team_a_players = explode(',', $match['team_a_players']);
65
            $team_b_players = explode(',', $match['team_b_players']);
66
67
            $dataBuilder = function(array $playerIDs, $isTeamB) use (&$insertData, $match) {
68
                foreach ($playerIDs as $playerID) {
69
                    if (empty($playerID)) {
70
                        continue;
71
                    }
72
73
                    $workspace = [
74
                        'match_id' => $match['id'],
75
                        'user_id' => $playerID,
76
                        'team_loyalty' => (int)$isTeamB,
77
                    ];
78
79
                    if ($match['team_a'] !== null && !$isTeamB) {
80
                        $workspace['team_id'] = $match['team_a'];
81
                    } elseif ($match['team_b'] !== null && $isTeamB) {
82
                        $workspace['team_id'] = $match['team_b'];
83
                    }
84
85
                    $insertData[] = $workspace;
86
                }
87
            };
88
89
            $dataBuilder($team_a_players, false);
90
            $dataBuilder($team_b_players, true);
91
        }
92
93
        // Only attempt to insert data if we actually have data to insert, otherwise an exception will be thrown
94
        if (!empty($insertData)) {
95
            $playerParticipationTable->insert($insertData);
96
            $playerParticipationTable->saveData();
97
        }
98
99
        $matchesTable = $this->table('matches');
100
        $matchesTable
101
            ->removeColumn('team_a_players')
102
            ->removeColumn('team_b_players')
103
            ->update()
104
        ;
105
    }
106
107
    public function down()
108
    {
109
        $matchesTable = $this->table('matches');
110
        $matchesTable
111
            ->addColumn('team_a_players', 'string', [
112
                'after' => 'team_b_points',
113
                'limit' => 256,
114
                'null' => true,
115
                'comment' => 'A comma-separated list of BZIDs of players who where on Team 1'
116
            ])
117
            ->addColumn('team_b_players', 'string', [
118
                'after' => 'team_a_players',
119
                'limit' => 256,
120
                'null' => true,
121
                'comment' => 'A comma-separated list of BZIDs of players who where on Team 2'
122
            ])
123
            ->update()
124
        ;
125
126
        $statement = $this->query('
127
            SELECT
128
              match_id, 
129
              GROUP_CONCAT(IF(team_loyalty = 0, user_id, NULL)) AS team_a_players,
130
              GROUP_CONCAT(IF(team_loyalty = 1, user_id, NULL)) AS team_b_players
131
            FROM
132
              match_participation
133
            GROUP BY
134
              match_id;
135
        ');
136
        $results = $statement->fetchAll();
0 ignored issues
show
Bug introduced by
The method fetchAll cannot be called on $statement (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
137
138
        foreach ($results as $result) {
139
            $this->execute(sprintf("
140
                UPDATE matches SET team_a_players = '%s', team_b_players = '%s' WHERE id = %d
141
            ", $result['team_a_players'], $result['team_b_players'], $result['match_id']));
142
        }
143
144
        $playerParticipationTable = $this->table('match_participation');
145
        $playerParticipationTable->drop();
146
    }
147
}
148