Completed
Branch merging-leagues-tournaments (46817d)
by Benedikt
01:48
created

EloRankingTest::testGetAdditionalFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Created by PhpStorm.
5
 * User: benedikt
6
 * Date: 1/3/18
7
 * Time: 3:53 PM
8
 */
9
10
namespace Tfboe\FmLib\Tests\Unit\Service\RankingSystem;
11
12
use Doctrine\Common\Collections\ArrayCollection;
13
use Doctrine\Common\Persistence\ObjectRepository;
14
use Doctrine\ORM\EntityManagerInterface;
15
use Tfboe\FmLib\Entity\Helpers\Result;
16
use Tfboe\FmLib\Entity\Helpers\TournamentHierarchyEntity;
17
use Tfboe\FmLib\Entity\RankingSystemChangeInterface;
18
use Tfboe\FmLib\Entity\RankingSystemListEntryInterface;
19
use Tfboe\FmLib\Entity\RankingSystemListInterface;
20
use Tfboe\FmLib\Service\ObjectCreatorServiceInterface;
21
use Tfboe\FmLib\Service\RankingSystem\EloRanking;
22
use Tfboe\FmLib\Service\RankingSystem\EntityComparerInterface;
23
use Tfboe\FmLib\Service\RankingSystem\TimeServiceInterface;
24
use Tfboe\FmLib\Tests\Entity\Game;
25
use Tfboe\FmLib\Tests\Entity\Player;
26
use Tfboe\FmLib\Tests\Entity\RankingSystemList;
27
use Tfboe\FmLib\Tests\Entity\RankingSystemListEntry;
28
use Tfboe\FmLib\Tests\Helpers\UnitTestCase;
29
30
/**
31
 * Class EloRankingTest
32
 * @packageTfboe\FmLib\Tests\Unit\Service\RankingSystemService
33
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
34
 */
35
class EloRankingTest extends UnitTestCase
36
{
37
//<editor-fold desc="Public Methods">
38
  /**
39
   * Provides data for all elo changes tests
40
   * @return array
41
   */
42
  public function providerEloChanges()
43
  {
44
    return [
45
      [false, Result::TEAM_A_WINS, [
46
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => 0.0,
47
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
48
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => 0.0,
49
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
50
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 0.0,
51
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
52
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 0.0,
53
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
54
      ]],
55
      [true, Result::TEAM_A_WINS, [
56
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => 7.8605068927035,
57
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
58
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => 7.8605068927035,
59
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
60
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => -7.8605068927035,
61
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
62
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 0.0,
63
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
64
      ]],
65
      [true, Result::TEAM_B_WINS, [
66
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => -12.139493107296,
67
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
68
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => -12.139493107296,
69
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
70
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 12.139493107296,
71
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
72
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 12.139493107296,
73
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
74
      ]],
75
      [true, Result::DRAW, [
76
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => -2.1394931072965,
77
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
78
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => -2.1394931072965,
79
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1400.5, "opponentElo" => 1325.0],
80
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 2.1394931072965,
81
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
82
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 2.1394931072965,
83
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1325.0, "opponentElo" => 1400.5],
84
      ]],
85
      [true, Result::NULLED, [
86
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => 0.0,
87
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
88
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => 0.0,
89
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
90
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 0.0,
91
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
92
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 0.0,
93
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
94
      ]],
95
      [true, Result::NOT_YET_FINISHED, [
96
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => 0.0,
97
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
98
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => 0.0,
99
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
100
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 0.0,
101
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
102
        ["points" => 1200.0, "rated" => 60, "played" => 70, "ranked" => 75, "pointChange" => 0.0,
103
          "ratedGamesChange" => 0, "playedChange" => 0, "teamElo" => 0.0, "opponentElo" => 0.0],
104
      ]],
105
      [true, Result::TEAM_A_WINS, [
106
        ["points" => 0.0, "rated" => 15, "played" => 19, "ranked" => 20, "pointChange" => 1515.78125,
107
          "ratedGamesChange" => 1, "playedChange" => 1, "provisoryRanking" => 1501.0, "provisoryChange" => 14.78125,
108
          "teamElo" => 0.0, "opponentElo" => 0.0],
109
        ["points" => 1300.0, "rated" => 20, "played" => 20, "ranked" => 26, "pointChange" => 0.0,
110
          "ratedGamesChange" => 0, "playedChange" => 1, "teamElo" => 0.0, "opponentElo" => 0.0],
111
        ["points" => 1450.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 0.0,
112
          "ratedGamesChange" => 0, "playedChange" => 1, "teamElo" => 0.0, "opponentElo" => 0.0],
113
        ["points" => 0.0, "rated" => 10, "played" => 10, "ranked" => 15, "pointChange" => 0.0,
114
          "ratedGamesChange" => 1, "playedChange" => 1, "provisoryRanking" => 1200.0,
115
          "provisoryChange" => -20.386363636364, "teamElo" => 0.0, "opponentElo" => 0.0],
116
      ]],
117
      [true, Result::TEAM_A_WINS, [
118
        ["points" => 0.0, "rated" => 15, "played" => 15, "ranked" => 20, "pointChange" => 0.0,
119
          "ratedGamesChange" => 1, "playedChange" => 1, "provisoryRanking" => 1501.0, "provisoryChange" => 6.1875,
120
          "teamElo" => 0.0, "opponentElo" => 0.0],
121
        ["points" => 2000.0, "rated" => 20, "played" => 20, "ranked" => 26, "pointChange" => 0.0,
122
          "ratedGamesChange" => 0, "playedChange" => 1, "teamElo" => 0.0, "opponentElo" => 0.0],
123
        ["points" => 1200.0, "rated" => 100, "played" => 100, "ranked" => 100, "pointChange" => 0.0,
124
          "ratedGamesChange" => 0, "playedChange" => 1, "teamElo" => 0.0, "opponentElo" => 0.0],
125
        ["points" => 0.0, "rated" => 10, "played" => 10, "ranked" => 15, "pointChange" => 0.0,
126
          "ratedGamesChange" => 1, "playedChange" => 1, "provisoryRanking" => 1200.0,
127
          "provisoryChange" => 31.863636363636, "teamElo" => 0.0, "opponentElo" => 0.0],
128
      ]],
129
      [true, Result::TEAM_A_WINS, [
130
        ["points" => 1501.0, "rated" => 53, "played" => 74, "ranked" => 102, "pointChange" => 4.7840781802172,
131
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1501.0, "opponentElo" => 1300.0],
132
        ["points" => 1300.0, "rated" => 20, "played" => 32, "ranked" => 26, "pointChange" => -4.7840781802172,
133
          "ratedGamesChange" => 1, "playedChange" => 1, "teamElo" => 1300.0, "opponentElo" => 1501.0],
134
      ]],
135
      [true, Result::TEAM_A_WINS, [
136
        ["points" => 0.0, "rated" => 15, "played" => 15, "ranked" => 20, "pointChange" => 0.0,
137
          "ratedGamesChange" => 1, "playedChange" => 1, "provisoryRanking" => 1501.0, "provisoryChange" => 12.4375,
138
          "teamElo" => 0.0, "opponentElo" => 1300.0],
139
        ["points" => 1300.0, "rated" => 20, "played" => 20, "ranked" => 26, "pointChange" => 0.0,
140
          "ratedGamesChange" => 0, "playedChange" => 1, "teamElo" => 1300.0, "opponentElo" => 0.0],
141
      ]],
142
    ];
143
  }
144
145
  /**
146
   * @dataProvider providerEloChanges
147
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::getChanges
148
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::computeChanges
149
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::getEloAverage
150
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::hasProvisoryEntry
151
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::addNotRatedChanges
152
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::getAdditionalChangeFields
153
   * @covers       \Tfboe\FmLib\Service\RankingSystem\EloRanking::getAdditionalFields
154
   * @covers       \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::getAdditionalChangeFields
155
   * @covers       \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::getOrCreateChange
156
   * @param bool $isPlayed if game was played
157
   * @param int $gameResult the game result
158
   * @param array $playerInfos all infos about each player and its expected changes
159
   * @uses         \Tfboe\FmLib\Entity\Helpers\SubClassData::__call
160
   * @uses         \Tfboe\FmLib\Entity\Helpers\SubClassData::getProperty
161
   * @uses         \Tfboe\FmLib\Entity\Helpers\SubClassData::initSubClassData
162
   * @uses         \Tfboe\FmLib\Entity\Helpers\SubClassData::setProperty
163
   * @uses         \Tfboe\FmLib\Entity\Traits\RankingSystemChange
164
   * @uses         \Tfboe\FmLib\Entity\Traits\RankingSystemListEntry
165
   * @uses         \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::__construct
166
   * @uses         \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::getEntriesOfPlayers
167
   * @uses         \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::getOrCreateRankingSystemListEntry
168
   * @SuppressWarnings(PHPMD.CyclomaticComplexity)
169
   */
170
  public function testGetChanges(bool $isPlayed, int $gameResult, array $playerInfos)
171
  {
172
    $repository = $this->createStub(ObjectRepository::class, ['findBy' => []]);
173
    /** @var EntityManagerInterface $entityManager */
174
    $entityManager = $this->createStub(EntityManagerInterface::class, ['getRepository' => $repository]);
175
    $service = $this->service($entityManager, $this->getObjectCreator());
176
    /** @var EloRanking $player1 */
177
178
    /** @var Player[] $players */
179
    $players = [];
180
    $playersAArray = [];
181
    $playersBArray = [];
182
    for ($i = 0; $i < count($playerInfos); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
183
      $players[$i] = $this->createStub(Player::class, ['getId' => $i]);
184
      if ($i < count($playerInfos) / 2) {
185
        $playersAArray[] = $players[$i];
186
      } else {
187
        $playersBArray[] = $players[$i];
188
      }
189
    }
190
191
    $playersA = new ArrayCollection($playersAArray);
192
    $playersB = new ArrayCollection($playersBArray);
193
    $game = $this->createStub(Game::class, [
194
      'getPlayersA' => $playersA,
195
      'getPlayersB' => $playersB,
196
    ]);
197
198
    $entriesArray = [];
199
    for ($i = 0; $i < count($playerInfos); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
200
      $entriesArray[$i] = $this->getRankingSystemListEntry($service, $players[$i]);
0 ignored issues
show
Bug introduced by
It seems like $players[$i] can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, Tfboe\FmLib\Tests\Unit\S...ankingSystemListEntry() does only seem to accept object<Tfboe\FmLib\Tests\Entity\Player>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
201
    }
202
    $entries = new ArrayCollection($entriesArray);
203
    $list = $this->createStub(RankingSystemList::class, ['getEntries' => $entries]);
204
    /** @var RankingSystemListInterface $list */
205
    foreach ($entries as $entry) {
206
      /** @var RankingSystemListEntryInterface $entry */
207
      $entry->setRankingSystemList($list);
208
    }
209
    for ($i = 0; $i < count($playerInfos); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
210
      $info = $playerInfos[$i];
211
      $entry = $list->getEntries()[$i];
212
      $entry->setPoints($info['points']);
213
      $entry->setPlayedGames($info['played']);
214
      $entry->setNumberRankedEntities($info['ranked']);
215
      $entry->setRatedGames($info['rated']);
216
      if (array_key_exists('provisoryRanking', $info)) {
217
        $list->getEntries()[$i]->setProvisoryRanking($info['provisoryRanking']);
218
      }
219
    }
220
    $game->method('isPlayed')->willReturn($isPlayed);
221
    $game->method('getResult')->willReturn($gameResult);
222
223
    /** @var RankingSystemChangeInterface[] $changes */
224
    $changes = static::callProtectedMethod($service, 'getChanges', [$game, $list]);
225
    self::assertEquals(count($playerInfos), count($changes));
226
    foreach ($players as $player) {
227
      $exists = false;
228
      foreach ($changes as $change) {
229
        if ($change->getPlayer() === $player) {
230
          $exists = true;
231
          break;
232
        }
233
      }
234
      self::assertTrue($exists);
235
    }
236
    /** @var Game $game */
237
    $this->assertChanges($changes, $playerInfos, $game);
238
  }
239
240
  /**
241
   * @covers \Tfboe\FmLib\Service\RankingSystem\EloRanking::startPoints
242
   * @uses   \Tfboe\FmLib\Service\RankingSystem\RankingSystemService::__construct
243
   */
244
  public function testStartPoints()
245
  {
246
    $service = $this->service();
247
    $startPoints = static::callProtectedMethod($service, 'startPoints', []);
248
    self::assertEquals(0.0, $startPoints);
249
  }
250
//</editor-fold desc="Public Methods">
251
252
//<editor-fold desc="Private Methods">
253
  /**
254
   * @param RankingSystemChangeInterface[] $changes
255
   * @param array $playerInfos
256
   * @param TournamentHierarchyEntity $entity
257
   */
258
  private function assertChanges(array $changes, array $playerInfos, TournamentHierarchyEntity $entity)
259
  {
260
    for ($i = 0; $i < count($changes); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
261
      $change = $changes[$i];
262
      self::assertEquals($entity, $change->getHierarchyEntity());
263
      self::assertEquals($playerInfos[$i]["pointChange"], $change->getPointsChange(), '', 0.01);
264
      self::assertEquals($playerInfos[$i]["ratedGamesChange"], $change->getRatedGames());
265
      self::assertEquals($playerInfos[$i]["playedChange"], $change->getPlayedGames());
266
      self::assertEquals(
267
        array_key_exists('provisoryChange', $playerInfos[$i]) ? $playerInfos[$i]['provisoryChange'] : 0,
268
        $change->getProvisoryRanking(), '', 0.01);
269
      self::assertEquals($playerInfos[$i]["teamElo"], $change->getTeamElo());
270
      self::assertEquals($playerInfos[$i]["opponentElo"], $change->getOpponentElo());
271
    }
272
  }
273
274
  /**
275
   * Creates a new ranking system list entry
276
   * @param EloRanking $service the elo ranking service to get additional fields
277
   * @param Player $player the player to use for the entry
278
   * @return RankingSystemListEntryInterface the created ranking system list entry
279
   */
280
  private function getRankingSystemListEntry(EloRanking $service, Player $player)
281
  {
282
    $entry = new RankingSystemListEntry(array_keys(static::callProtectedMethod($service, 'getAdditionalFields')));
283
    $entry->setPlayer($player);
284
    return $entry;
285
  }
286
287
  /**
288
   * Gets an elo ranking service
289
   * @param EntityManagerInterface|null $entityManager
290
   * @param null|ObjectCreatorServiceInterface $objectCreatorService
291
   * @return EloRanking
292
   */
293
  private function service(?EntityManagerInterface $entityManager = null,
294
                           ?ObjectCreatorServiceInterface $objectCreatorService = null)
295
  {
296
    if ($entityManager === null) {
297
      $entityManager = $this->createMock(EntityManagerInterface::class);
298
    }
299
    if ($objectCreatorService === null) {
300
      $objectCreatorService = $this->createMock(ObjectCreatorServiceInterface::class);
301
    }
302
    /** @noinspection PhpParamsInspection */
303
    return new EloRanking(
304
      $entityManager, $this->createMock(TimeServiceInterface::class),
0 ignored issues
show
Bug introduced by
It seems like $entityManager can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, Tfboe\FmLib\Service\Rank...mService::__construct() does only seem to accept object<Doctrine\ORM\EntityManagerInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Documentation introduced by
$this->createMock(\Tfboe...erviceInterface::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Tfboe\FmLib\Servi...m\TimeServiceInterface>.

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...
305
      $this->createMock(EntityComparerInterface::class), $objectCreatorService
0 ignored issues
show
Documentation introduced by
$this->createMock(\Tfboe...mparerInterface::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Tfboe\FmLib\Servi...ntityComparerInterface>.

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...
Bug introduced by
It seems like $objectCreatorService can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, Tfboe\FmLib\Service\Rank...mService::__construct() does only seem to accept object<Tfboe\FmLib\Servi...reatorServiceInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
306
    );
307
  }
308
//</editor-fold desc="Private Methods">
309
}