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

MatchesTableRestructure   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 2
dl 0
loc 143
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
B down() 0 40 2
C up() 0 94 9
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