OutfitProfileTransformer   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 241
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
dl 0
loc 241
rs 10
c 0
b 0
f 0
wmc 23
lcom 1
cbo 13

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A transform() 0 15 1
A includeFacilities() 0 17 3
B getCaptureStats() 0 31 4
A includeInvolvement() 0 5 1
B includeMetrics() 0 24 2
A includePlayers() 0 22 3
B getOutfitPlayers() 0 33 3
B getOutfitMembers() 0 38 5
1
<?php
2
3
namespace Ps2alerts\Api\Transformer\Profiles;
4
5
use League\Fractal\TransformerAbstract;
6
use Ps2alerts\Api\Contract\DatabaseAwareInterface;
7
use Ps2alerts\Api\Contract\DatabaseAwareTrait;
8
use Ps2alerts\Api\Contract\HttpClientAwareInterface;
9
use Ps2alerts\Api\Contract\HttpClientAwareTrait;
10
use Ps2alerts\Api\Contract\RedisAwareInterface;
11
use Ps2alerts\Api\Contract\RedisAwareTrait;
12
use Ps2alerts\Api\Repository\Metrics\MapRepository;
13
use Ps2alerts\Api\Repository\Metrics\OutfitRepository;
14
use Ps2alerts\Api\Repository\Metrics\OutfitTotalRepository;
15
use Ps2alerts\Api\Repository\Metrics\PlayerRepository;
16
use Ps2alerts\Api\Repository\Metrics\PlayerTotalRepository;
17
use Ps2alerts\Api\Transformer\Profiles\OutfitInvolvementTransformer;
18
use Ps2alerts\Api\Transformer\Profiles\OutfitPlayersTransformer;
19
20
class OutfitProfileTransformer extends TransformerAbstract implements
21
    DatabaseAwareInterface,
22
    HttpClientAwareInterface,
23
    RedisAwareInterface
24
{
25
    use DatabaseAwareTrait;
26
    use HttpClientAwareTrait;
27
    use RedisAwareTrait;
28
29
    /**
30
     * List of available includes to this resource
31
     *
32
     * @var array
33
     */
34
    protected $availableIncludes = [
35
        'facilities',
36
        'involvement',
37
        'metrics',
38
        'players'
39
    ];
40
41
    protected $mapRepo;
42
    protected $outfitRepo;
43
    protected $outfitTotalRepo;
44
    protected $playerRepo;
45
    protected $playerTotalRepo;
46
47
    public function __construct(
48
        MapRepository         $mapRepo,
49
        OutfitRepository      $outfitRepo,
50
        OutfitTotalRepository $outfitTotalRepo,
51
        PlayerRepository      $playerRepo,
52
        PlayerTotalRepository $playerTotalRepo
53
    ) {
54
        $this->mapRepo         = $mapRepo;
55
        $this->outfitRepo      = $outfitRepo;
56
        $this->outfitTotalRepo = $outfitTotalRepo;
57
        $this->playerRepo      = $playerRepo;
58
        $this->playerTotalRepo = $playerTotalRepo;
59
    }
60
61
    /**
62
     * The transform method required by Fractal to parse the data and return proper typing and fields.
63
     *
64
     * @param  array $data Data to transform
65
     *
66
     * @return array
67
     */
68
    public function transform($data)
69
    {
70
        return [
71
            'id'        => (string) $data['outfitID'], // Bigint
72
            'name'      => (string) $data['outfitName'],
73
            'tag'       => (string) $data['outfitTag'],
74
            'faction'   => (int) $data['outfitFaction'],
75
            'kills'     => (int) $data['outfitKills'],
76
            'deaths'    => (int) $data['outfitDeaths'],
77
            'teamkills' => (int) $data['outfitTKs'],
78
            'suicides'  => (int) $data['outfitSuicides'],
79
            'server'    => (int) $data['outfitServer'],
80
            'captures'  => (int) $data['outfitCaptures']
81
        ];
82
    }
83
84
    public function includeFacilities($data)
85
    {
86
        $redis = $this->getRedisDriver();
87
        $key = "ps2alerts:api:profiles:outfit:captures:{$data['outfitID']}";
88
89
        if ($redis->exists($key)) {
90
            $bases = json_decode($redis->get($key), true);
91
        } else {
92
            $bases = $this->getCaptureStats($data);
93
94
            if (count($bases) > 0) {
95
                $redis->setEx($key, 3600, json_encode($bases));
96
            }
97
        }
98
99
        return $this->collection($bases, new OutfitCaptureTransformer);
0 ignored issues
show
Documentation introduced by
new \Ps2alerts\Api\Trans...fitCaptureTransformer() is of type object<Ps2alerts\Api\Tra...tfitCaptureTransformer>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
100
    }
101
102
    public function getCaptureStats($data)
103
    {
104
        // For some reason, auraSQL or my abstraction code won't handle this. Time to do it manually.
105
106
        $pdo = $this->getDatabaseDriver();
107
108
        $statement = $pdo->prepare("SELECT defence, facilityID FROM ws_map WHERE outfitCaptured = ?");
109
        $statement->bindValue(1, $data['outfitID']);
110
        $statement->execute();
111
112
        $bases = [];
113
114
        while ($row = $statement->fetch(\PDO::FETCH_OBJ)) {
115
            if (empty($bases[$row->facilityID])) {
116
                $bases[$row->facilityID] = [
117
                    'facility' => $row->facilityID,
118
                    'captures' => 0,
119
                    'defences' => 0
120
                ];
121
            }
122
123
            if ($row->defence === '1') {
124
                $bases[$row->facilityID]['defences']++;
125
126
            } else {
127
                $bases[$row->facilityID]['captures']++;
128
            }
129
        }
130
131
        return $bases;
132
    }
133
134
    public function includeInvolvement($data)
135
    {
136
        $data = $this->outfitRepo->readAllByIdWithArchive($data['outfitID'], 'outfitID');
137
        return $this->collection($data, new OutfitInvolvementTransformer);
0 ignored issues
show
Documentation introduced by
new \Ps2alerts\Api\Trans...nvolvementTransformer() is of type object<Ps2alerts\Api\Tra...InvolvementTransformer>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
138
    }
139
140
    public function includeMetrics($data)
141
    {
142
        $metrics = [
143
            'kills'     => 0,
144
            'deaths'    => 0,
145
            'teamkills' => 0,
146
            'suicides'  => 0,
147
            'headshots' => 0
148
        ];
149
150
        $alerts = $this->outfitRepo->readAllByIdWithArchive($data['outfitID'], 'outfitID');
151
        $count = count($alerts);
152
        $metrics['involvement'] = $count;
153
154
        // Calculate metrics
155
        for ($i = 0; $i < $count; $i++) {
156
            $metrics['kills']     = $metrics['kills'] + $alerts[$i]['outfitKills'];
157
            $metrics['deaths']    = $metrics['deaths'] + $alerts[$i]['outfitDeaths'];
158
            $metrics['teamkills'] = $metrics['teamkills'] + $alerts[$i]['outfitTKs'];
159
            $metrics['suicides']  = $metrics['suicides'] + $alerts[$i]['outfitSuicides'];
160
        }
161
162
        return $this->item($metrics, new OutfitMetricsTransformer);
0 ignored issues
show
Documentation introduced by
new \Ps2alerts\Api\Trans...fitMetricsTransformer() is of type object<Ps2alerts\Api\Tra...tfitMetricsTransformer>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
163
    }
164
165
    public function includePlayers($data)
166
    {
167
        $chars = $this->getOutfitMembers($data, 0);
168
169
        // If we've hit the upper census limit
170
        if (count($chars) == 5000) {
171
            $chars = array_merge($chars, $this->getOutfitMembers($data, 5000));
172
        }
173
174
        $count = count($chars);
175
176
        if ($count == 0) {
177
            return null;
178
        }
179
180
        $players = $this->getOutfitPlayers($data, $chars);
181
182
        return $this->collection(
183
            $players,
184
            new OutfitPlayersTransformer
0 ignored issues
show
Documentation introduced by
new \Ps2alerts\Api\Trans...fitPlayersTransformer() is of type object<Ps2alerts\Api\Tra...tfitPlayersTransformer>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
185
        );
186
    }
187
188
    public function getOutfitPlayers($data, $chars)
189
    {
190
        $redis = $this->getRedisDriver();
191
        $key = "ps2alerts:api:profiles:outfit:players:{$data['outfitID']}";
192
193
        // If we have this cached already
194
        if (! empty($redis->exists($key))) {
195
            return json_decode($redis->get($key), true);
196
        }
197
198
        $count = count($chars);
199
        $whereIn = '';
200
201
        // Get all members out of the database
202
        for ($i = 0; $i < $count; $i++) {
203
            $whereIn .= "'{$chars[$i]}',";
204
        }
205
206
        // Trim trailing comma
207
        $whereIn = rtrim($whereIn, ',');
208
209
        $query = $this->playerTotalRepo->newQuery();
210
211
        $query->cols(['playerID, playerName, playerKills, playerDeaths, playerTeamKills, playerSuicides, headshots']);
212
        $query->where("playerID IN ({$whereIn})");
213
214
        $players = $this->playerTotalRepo->fireStatementAndReturn($query);
215
216
        // Cache results in redis
217
        $redis->setEx($key, 3600, json_encode($players));
218
219
        return $players;
220
    }
221
222
    public function getOutfitMembers($data, $offset)
223
    {
224
        $client = $this->getHttpClientDriver();
225
        $redis = $this->getRedisDriver();
226
227
        $key = "ps2alerts:api:profiles:outfit:census:members:{$data['outfitID']}:{$offset}";
228
229
        // If we have this cached already
230
        if (! empty($redis->exists($key))) {
231
            return json_decode($redis->get($key));
232
        }
233
234
        $namespace = 'ps2:v2';
235
236
        if ($data['outfitServer'] >= 2000) {
237
            $namespace = 'ps2ps4eu';
238
        } elseif ($data['outfitServer'] >= 1000) {
239
            $namespace = 'ps2ps4us';
240
        }
241
242
        $response = $client->get(
243
            "https://census.daybreakgames.com/s:planetside2alertstats/get/{$namespace}/outfit_member?outfit_id={$data['outfitID']}&c:limit=5000&c:start={$offset}"
244
        );
245
246
        $body = json_decode($response->getBody()->getContents(), true);
247
248
        $count = count($body['outfit_member_list']);
249
        $chars = [];
250
251
        for ($i = 0; $i < $count; $i++) {
252
            $chars[] = $body['outfit_member_list'][$i]['character_id'];
253
        }
254
255
        // Cache results in redis
256
        $redis->setEx($key, 3600, json_encode($chars));
257
258
        return $chars;
259
    }
260
}
261