Completed
Push — master ( e5ab12...9197f0 )
by Konstantinos
09:09
created

Team::getActiveStatuses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * This file contains functionality relating to the teams belonging to the current league
4
 *
5
 * @package    BZiON\Models
6
 * @license    https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3
7
 */
8
9
/**
10
 * A league team
11
 * @package    BZiON\Models
12
 */
13
class Team extends AvatarModel
14
{
15
    /**
16
     * The description of the team written in markdown
17
     *
18
     * @var string
19
     */
20
    protected $description;
21
22
    /**
23
     * The creation date of the team
24
     *
25
     * @var TimeDate
26
     */
27
    protected $created;
28
29
    /**
30
     * The team's current elo
31
     *
32
     * @var int
33
     */
34
    protected $elo;
35
36
    /**
37
     * The team's activity
38
     *
39
     * @var float
40
     */
41
    protected $activity;
42
43
    /**
44
     * The id of the team leader
45
     *
46
     * @var int
47
     */
48
    protected $leader;
49
50
    /**
51
     * The number of matches won
52
     *
53
     * @var int
54
     */
55
    protected $matches_won;
56
57
    /**
58
     * The number of matches lost
59
     *
60
     * @var int
61
     */
62
    protected $matches_lost;
63
64
    /**
65
     * The number of matches tied
66
     *
67
     * @var int
68
     */
69
    protected $matches_draw;
70
71
    /**
72
     * The total number of matches
73
     *
74
     * @var int
75
     */
76
    protected $matches_total;
77
78
    /**
79
     * The number of members
80
     *
81
     * @var int
82
     */
83
    protected $members;
84
85
    /**
86
     * The team's status
87
     *
88
     * @var string
89
     */
90
    protected $status;
91
92
    /**
93
     * The name of the database table used for queries
94
     */
95
    const TABLE = "teams";
96
97
    /**
98
     * The location where avatars will be stored
99
     */
100
    const AVATAR_LOCATION = "/web/assets/imgs/avatars/teams/";
101
102
    const CREATE_PERMISSION = Permission::CREATE_TEAM;
103
    const EDIT_PERMISSION = Permission::EDIT_TEAM;
104
    const SOFT_DELETE_PERMISSION = Permission::SOFT_DELETE_TEAM;
105
    const HARD_DELETE_PERMISSION = Permission::HARD_DELETE_TEAM;
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 17
    protected function assignResult($team)
111
    {
112 17
        $this->name = $team['name'];
113 17
        $this->alias = $team['alias'];
114 17
        $this->description = $team['description'];
115 17
        $this->avatar = $team['avatar'];
116 17
        $this->created = TimeDate::fromMysql($team['created']);
117 17
        $this->elo = $team['elo'];
118 17
        $this->activity = $team['activity'];
119 17
        $this->leader = $team['leader'];
120 17
        $this->matches_won = $team['matches_won'];
121 17
        $this->matches_lost = $team['matches_lost'];
122 17
        $this->matches_draw = $team['matches_draw'];
123 17
        $this->members = $team['members'];
124 17
        $this->status = $team['status'];
125
126 17
        $this->matches_total = $this->matches_won + $this->matches_lost + $this->matches_draw;
127 17
    }
128
129
    /**
130
     * Adds a new member to the team
131
     *
132
     * @param int $id The id of the player to add to the team
133
     *
134
     * @return bool|null True if both the player was added to the team AND the team member count was incremented
135
     */
136 17
    public function addMember($id)
137
    {
138 17
        $player = Player::get($id);
139
140 17
        if (!$player->isTeamless()) {
141
            throw new Exception("The player already belongs in a team");
142
        }
143
144 17
        $player->setTeam($this->getId());
145 17
        $this->update('members', ++$this->members, "i");
146 17
    }
147
148
    /**
149
     * Increase or decrease the ELO of the team
150
     *
151
     * @param int $adjust The value to be added to the current ELO (negative to substract)
152
     */
153 8
    public function changeElo($adjust)
154
    {
155 8
        $this->elo += $adjust;
156 8
        $this->update("elo", $this->elo, "i");
157 8
    }
158
159
    /**
160
     * Increment the team's match count
161
     *
162
     * @param int    $adjust The number to add to the current matches number (negative to substract)
163
     * @param string $type   The match count that should be changed. Can be 'win', 'draw' or 'loss'
164
     */
165 8
    public function changeMatchCount($adjust, $type)
166
    {
167 8
        $this->matches_total += $adjust;
168
169
        switch ($type) {
170 8
            case "win":
171
            case "won":
172 5
                $this->update("matches_won", $this->matches_won += $adjust, "i");
173
174 5
                return;
175
            case "loss":
176 3
            case "lost":
177 5
                $this->update("matches_lost", $this->matches_lost += $adjust, "i");
178
179 5
                return;
180
            default:
181 3
                $this->update("matches_draw", $this->matches_draw += $adjust, "i");
182
183 3
                return;
184
        }
185
    }
186
187
    /**
188
     * Decrement the team's match count by one
189
     *
190
     * @param string $type The type of the match. Can be 'win', 'draw' or 'loss'
191
     */
192
    public function decrementMatchCount($type)
193
    {
194
        $this->changeMatchCount(-1, $type);
195
    }
196
197
    /**
198
     * Get the activity of the team
199
     *
200
     * @return string The team's activity formatted to two decimal places
201
     */
202
    public function getActivity()
203
    {
204
        return sprintf("%.2f", $this->activity);
205
    }
206
207
    /**
208
     * Get the creation date of the team
209
     *
210
     * @return TimeDate The creation date of the team
211
     */
212 1
    public function getCreationDate()
213
    {
214 1
        return $this->created;
215
    }
216
217
    /**
218
     * Get the description of the team
219
     *
220
     * @param  bool $md false for HTML format, true for the original markdown
0 ignored issues
show
Bug introduced by
There is no parameter named $md. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
221
     * @return string  The description of the team
222
     */
223
    public function getDescription()
224
    {
225
        return $this->description;
226
    }
227
228
    /**
229
     * Get the current elo of the team
230
     *
231
     * @return int The elo of the team
232
     */
233 8
    public function getElo()
234
    {
235 8
        return $this->elo;
236
    }
237
238
    /**
239
     * Get the leader of the team
240
     *
241
     * @return Player The object representing the team leader
242
     */
243 1
    public function getLeader()
244
    {
245 1
        return Player::get($this->leader);
246
    }
247
248
    /**
249
     * Get the matches this team has participated in
250
     *
251
     * @param string $matchType The filter for match types: "all", "wins", "losses", or "draws"
252
     * @param int    $count     The amount of matches to be retrieved
253
     * @param int    $page      The number of the page to return
254
     *
255
     * @return Match[] The array of match IDs this team has participated in
256
     */
257 1
    public function getMatches($matchType = "all", $count = 5, $page = 1)
258
    {
259 1
        return Match::getQueryBuilder()
260 1
             ->active()
261 1
             ->with($this, $matchType)
262 1
             ->sortBy('time')->reverse()
263 1
             ->limit($count)->fromPage($page)
264 1
             ->getModels();
265
    }
266
267
    /**
268
     * Get the number of matches that resulted as a draw
269
     *
270
     * @return int The number of matches, respectively
271
     */
272
    public function getMatchesDraw()
273
    {
274
        return $this->matches_draw;
275
    }
276
277
    /**
278
     * Get the number of matches that the team has lost
279
     *
280
     * @return int The number of matches, respectively
281
     */
282
    public function getMatchesLost()
283
    {
284
        return $this->matches_lost;
285
    }
286
287
    /**
288
     * Get the URL that points to the team's list of matches
289
     *
290
     * @return string The team's list of matches
291
     */
292
    public function getMatchesURL()
293
    {
294
        return Service::getGenerator()->generate("match_by_team_list", array("team" => $this->getAlias()));
295
    }
296
297
    /**
298
     * Get the number of matches that the team has won
299
     *
300
     * @return int The number of matches, respectively
301
     */
302
    public function getMatchesWon()
303
    {
304
        return $this->matches_won;
305
    }
306
307
    /**
308
     * Get the members on the team
309
     *
310
     * @return Player[] The members on the team
311
     */
312 1
    public function getMembers()
313
    {
314 1
        $leader = $this->leader;
315 1
        $members = Player::getTeamMembers($this->id);
316
317
        usort($members, function ($a, $b) use ($leader) {
318
            // Leader always goes first
319 1
            if ($a->getId() == $leader) {
320 1
                return -1;
321
            }
322
            if ($b->getId() == $leader) {
323
                return 1;
324
            }
325
326
            // Sort the rest of the players alphabetically
327
            $sort = Player::getAlphabeticalSort();
328
329
            return $sort($a, $b);
330 1
        });
331
332 1
        return $members;
333
    }
334
335
    /**
336
     * Get the name of the team
337
     *
338
     * @return string The name of the team
339
     */
340 17
    public function getName()
341
    {
342 17
        if ($this->name === null) {
343
            return "None";
344
        }
345 17
        return $this->name;
346
    }
347
348
    /**
349
     * Get the name of the team, safe for use in your HTML
350
     *
351
     * @return string The name of the team
352
     */
353
    public function getEscapedName()
354
    {
355
        if (!$this->valid) {
356
            return "<em>None</em>";
357
        }
358
        return $this->escape($this->name);
359
    }
360
361
    /**
362
     * Get the number of members on the team
363
     *
364
     * @return int The number of members on the team
365
     */
366 1
    public function getNumMembers()
367
    {
368 1
        return $this->members;
369
    }
370
371
    /**
372
     * Get the total number of matches this team has played
373
     *
374
     * @return int The total number of matches this team has played
375
     */
376 1
    public function getNumTotalMatches()
377
    {
378 1
        return $this->matches_total;
379
    }
380
381
    /**
382
     * Get the rank category a team belongs too based on their ELO
383
     *
384
     * This value is always a multiple of 100 and less than or equal to 2000
385
     *
386
     * @return int The rank category a team belongs to
387
     */
388
    public function getRankValue()
389
    {
390
        return min(2000, floor($this->getElo() / 100) * 100);
391
    }
392
393
    /**
394
     * Get the HTML for an image with the rank symbol
395
     *
396
     * @return string The HTML for a rank image
397
     */
398
    public function getRankImageLiteral()
399
    {
400
        return '<div class="c-rank c-rank--' . $this->getRankValue() . '"></div>';
401
    }
402
403
    /**
404
     * Increment the team's match count by one
405
     *
406
     * @param string $type The type of the match. Can be 'win', 'draw' or 'loss'
407
     */
408
    public function incrementMatchCount($type)
409
    {
410
        $this->changeMatchCount(1, $type);
411
    }
412
413
    /**
414
     * Check if a player is part of this team
415
     *
416
     * @param int $playerID The player to check
417
     *
418
     * @return bool True if the player belongs to this team
419
     */
420 1
    public function isMember($playerID)
421
    {
422 1
        $player = Player::get($playerID);
423
424 1
        return ($player->getTeam()->isSameAs($this));
425
    }
426
427
    /**
428
     * Removes a member from the team
429
     *
430
     * @param  int  $id The id of the player to remove
431
     * @return void
432
     */
433 1
    public function removeMember($id)
434
    {
435 1
        if (!$this->isMember($id)) {
436
            throw new Exception("The player is not a member of that team");
437
        }
438
439 1
        $player = Player::get($id);
440
441 1
        $player->update("team", null, "s");
442 1
        $this->update('members', --$this->members, "i");
443 1
    }
444
445
    /**
446
     * Update the description of the team
447
     *
448
     * @param  string $description The description of the team written as markdown
449
     * @return void
450
     */
451
    public function setDescription($description)
452
    {
453
        $this->update("description", $description, "s");
454
    }
455
456
    /**
457
     * Change the status of the team
458
     *
459
     * @param  string $newStatus The new status of the team (open, closed, disabled or deleted)
460
     * @return self
461
     */
462
    public function setStatus($newStatus)
463
    {
464
        return $this->updateProperty($this->status, 'status', $newStatus, 's');
465
    }
466
467
    /**
468
     * Change the leader of the team
469
     *
470
     * @param  int  $leader The ID of the new leader of the team
471
     * @return self
472
     */
473
    public function setLeader($leader)
474
    {
475
        return $this->updateProperty($this->leader, 'leader', $leader, 'i');
476
    }
477
478
    /**
479
     * Find if a specific match is the team's last one
480
     *
481
     * @param  int  $matchID The ID of the match
482
     * @return bool
483
     */
484
    public function isLastMatch($matchID)
485
    {
486
        // Find if this team participated in any matches after the current match
487
        return !Match::getQueryBuilder()
488
            ->with($this)
489
            ->active()
490
            ->sortBy('id')->reverse()
491
            ->startAt($matchID)
492
            ->any();
493
    }
494
495
    /**
496
     * {@inheritdoc}
497
     */
498
    public function delete()
499
    {
500
        parent::delete();
501
502
        // Remove all the members of a deleted team
503
        $this->updateProperty($this->members, 'members', 0, 'i');
504
        $this->db->query("UPDATE `players` SET `team` = NULL WHERE `team` = ?",
505
            'i', $this->id);
506
    }
507
508
    /**
509
     * Create a new team
510
     *
511
     * @param  string           $name        The name of the team
512
     * @param  int              $leader      The ID of the person creating the team, also the leader
513
     * @param  string           $avatar      The URL to the team's avatar
514
     * @param  string           $description The team's description
515
     * @param  string           $status      The team's status (open, closed, disabled or deleted)
516
     * @param  string|\TimeDate $created     The date the team was created
517
     *
518
     * @return Team   An object that represents the newly created team
519
     */
520 18
    public static function createTeam($name, $leader, $avatar, $description, $status = 'closed', $created = "now")
521
    {
522 18
        $created = TimeDate::from($created);
523
524 18
        $team = self::create(array(
525 18
            'name'         => $name,
526 18
            'alias'        => self::generateAlias($name),
527 18
            'description'  => $description,
528 18
            'elo'          => 1200,
529 18
            'activity'     => 0.00,
530 18
            'matches_won'  => 0,
531 18
            'matches_draw' => 0,
532 18
            'matches_lost' => 0,
533 18
            'members'      => 0,
534 18
            'avatar'       => $avatar,
535 18
            'leader'       => $leader,
536 18
            'status'       => $status,
537 18
            'created'      => $created->toMysql(),
538 18
        ), 'sssidiiiissss');
539
540 17
        $team->addMember($leader);
541 17
        $team->getIdenticon($team->getId());
542
543 17
        return $team;
544
    }
545
546
    /**
547
     * Get all the teams in the database that are not disabled or deleted
548
     *
549
     * @return Team[] An array of Team IDs
550
     */
551
    public static function getTeams()
552
    {
553
        return self::arrayIdToModel(
554
            parent::fetchIdsFrom(
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (fetchIdsFrom() instead of getTeams()). Are you sure this is correct? If so, you might want to change this to $this->fetchIdsFrom().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
555
                "status", array("disabled", "deleted"),
556
                "s", true, "ORDER BY elo DESC"
557
            )
558
        );
559
    }
560
561
    /**
562
     * Get a single team by its name
563
     *
564
     * @param  string $name The team name to look for
565
     * @return Team
566
     */
567
    public static function getFromName($name)
568
    {
569
        $team = static::get(self::fetchIdFrom($name, 'name', 's'));
570
571
        return $team->inject('name', $name);
572
    }
573
574
    /**
575
     * Alphabetical order function for use in usort (case-insensitive)
576
     * @return Closure The sort function
577
     */
578
    public static function getAlphabeticalSort()
579
    {
580
        return function (Team $a, Team $b) {
581
            return strcasecmp($a->getName(), $b->getName());
582
        };
583
    }
584
585
    /**
586
     * {@inheritdoc}
587
     */
588
    public static function getActiveStatuses()
589
    {
590
        return array('open', 'closed');
591
    }
592
593
    /**
594
     * Get a query builder for teams
595
     * @return QueryBuilder
596
     */
597 View Code Duplication
    public static function getQueryBuilder()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
598
    {
599
        return new QueryBuilder('Team', array(
600
            'columns' => array(
601
                'name'   => 'name',
602
                'status' => 'status'
603
            ),
604
            'name' => 'name',
605
        ));
606
    }
607
608
    /**
609
     * {@inheritdoc}
610
     */
611
    protected function isEditor($player)
612
    {
613
        return $player->isSameAs($this->getLeader());
614
    }
615
}
616