Issues (72)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Game/Round.php (33 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Cysha\Casino\Holdem\Game;
4
5
use Cysha\Casino\Cards\Contracts\CardResults;
6
use Cysha\Casino\Game\Chips;
7
use Cysha\Casino\Game\ChipStackCollection;
8
use Cysha\Casino\Game\Contracts\Dealer as DealerContract;
9
use Cysha\Casino\Game\Contracts\GameParameters;
10
use Cysha\Casino\Game\Contracts\Player as PlayerContract;
11
use Cysha\Casino\Game\PlayerCollection;
12
use Cysha\Casino\Holdem\Exceptions\RoundException;
13
use Cysha\Casino\Holdem\Game\LeftToAct;
14
use Ramsey\Uuid\Uuid;
15
16
class Round
17
{
18
    /**
19
     * @var Uuid
20
     */
21
    private $id;
22
23
    /**
24
     * @var Table
25
     */
26
    private $table;
27
28
    /**
29
     * @var ChipStackCollection
30
     */
31
    private $betStacks;
32
33
    /**
34
     * @var PlayerCollection
35
     */
36
    private $foldedPlayers;
37
38
    /**
39
     * @var ChipPotCollection
40
     */
41
    private $chipPots;
42
43
    /**
44
     * @var ChipPot
45
     */
46
    private $currentPot;
47
48
    /**
49
     * @var ActionCollection
50
     */
51
    private $actions;
52
53
    /**
54
     * @var PlayerCollection
55
     */
56
    private $leftToAct;
57
58
    /**
59
     * @var GameParameters
60
     */
61
    private $gameRules;
62
63
    /**
64
     * Round constructor.
65
     *
66
     * @param Uuid $id
67
     * @param Table $table
68
     * @param GameParameters $gameRules
69
     */
70
    private function __construct(Uuid $id, Table $table, GameParameters $gameRules)
71
    {
72
        $this->id = $id;
73
        $this->table = $table;
74
        $this->chipPots = ChipPotCollection::make();
75
        $this->currentPot = ChipPot::create();
76
        $this->betStacks = ChipStackCollection::make();
77 50
        $this->foldedPlayers = PlayerCollection::make();
78
        $this->actions = ActionCollection::make();
79 50
        $this->leftToAct = LeftToAct::make();
80 50
        $this->gameRules = $gameRules;
81 50
82 50
        // shuffle the deck ready
83 50
        $this->dealer()->shuffleDeck();
84 50
85 50
        // add the default pot to the chipPots
86 50
        $this->chipPots->push($this->currentPot);
87 50
88 50
        // init the betStacks and actions for each player
89
        $this->resetBetStacks();
90
        $this->setupLeftToAct();
91 50
    }
92
93
    /**
94 50
     * Start a Round of poker.
95
     *
96
     * @param Uuid $id
97 50
     * @param Table $table
98 50
     * @param GameParameters $gameRules
99 50
     *
100
     * @return Round
101
     */
102
    public static function start(Uuid $id, Table $table, GameParameters $gameRules): Round
103
    {
104
        return new static($id, $table, $gameRules);
105
    }
106
107
    /**
108 50
     * Run the cleanup procedure for an end of Round.
109
     */
110 50
    public function end()
111
    {
112
        $this->dealer()->checkCommunityCards();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method checkCommunityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
113
114
        $this->collectChipTotal();
115
116 11
        $this->distributeWinnings();
117
118
        $this->table()->moveButton();
119
    }
120 11
121
    /**
122 11
     * @return Uuid
123
     */
124 11
    public function id(): Uuid
125 11
    {
126
        return $this->id;
127
    }
128
129
    /**
130 50
     * @return DealerContract
131
     */
132 50
    public function dealer(): DealerContract
133
    {
134
        return $this->table->dealer();
135
    }
136
137
    /**
138 3
     * @return PlayerCollection
139
     */
140 3
    public function players(): PlayerCollection
141
    {
142
        return $this->table->players();
143
    }
144
145
    /**
146 12
     * @return PlayerCollection
147
     */
148 12
    public function playersStillIn(): PlayerCollection
149
    {
150
        return $this->table->playersSatDown()->diff($this->foldedPlayers());
151
    }
152
153
    /**
154 19
     * @return PlayerCollection
155
     */
156 19
    public function foldedPlayers(): PlayerCollection
157
    {
158
        return $this->foldedPlayers;
159
    }
160
161
    /**
162 1
     * @return ActionCollection
163
     */
164 1
    public function actions(): ActionCollection
165
    {
166
        return $this->actions;
167
    }
168
169
    /**
170 35
     * @return LeftToAct
171
     */
172 35
    public function leftToAct(): LeftToAct
173
    {
174
        return $this->leftToAct;
175
    }
176
177
    /**
178 36
     * @return Table
179
     */
180 36
    public function table(): Table
181
    {
182
        return $this->table;
183
    }
184
185
    /**
186 50
     * @return ChipStackCollection
187
     */
188 50
    public function betStacks(): ChipStackCollection
189
    {
190
        return $this->betStacks;
191
    }
192
193
    /**
194 13
     * @return GameParameters
195
     */
196 13
    public function gameRules(): GameParameters
197
    {
198
        return $this->gameRules;
199
    }
200
201
    /**
202 29
     * @return int
203
     */
204 29
    public function betStacksTotal(): int
205
    {
206
        return $this->betStacks()->total()->amount();
207
    }
208
209
    public function dealHands()
210 22
    {
211
        $players = $this->table()
212 22
            ->playersSatDown()
213 22
            ->resetPlayerListFromSeat($this->table()->button() + 1);
214
215
        $this->dealer()->dealHands($players);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method dealHands() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
216
    }
217
218 2
    /**
219
     * Runs over each chipPot and assigns the chips to the winning player.
220 2
     */
221
    private function distributeWinnings()
222
    {
223
        $this->chipPots()
224
            ->reverse()
225
            ->each(function (ChipPot $chipPot) {
226 11
                // if only 1 player participated to pot, he wins it no arguments
227
                if ($chipPot->players()->count() === 1) {
228 11
                    $potTotal = $chipPot->chips()->total();
229 11
230
                    $chipPot->players()->first()->chipStack()->add($potTotal);
231
232 11
                    $this->chipPots()->remove($chipPot);
233 6
234
                    return;
235 6
                }
236
237 6
                $activePlayers = $chipPot->players()->diff($this->foldedPlayers());
238
239 6
                $playerHands = $this->dealer()->hands()->findByPlayers($activePlayers);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method hands() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
240
                $evaluate = $this->dealer()->evaluateHands($this->dealer()->communityCards(), $playerHands);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
241
242 11
                // if just 1, the player with that hand wins
243
                if ($evaluate->count() === 1) {
244 11
                    $player = $evaluate->first()->hand()->player();
245 11
                    $potTotal = $chipPot->chips()->total();
246
247
                    $player->chipStack()->add($potTotal);
248 11
249 11
                    $this->chipPots()->remove($chipPot);
250 11
                } else {
251
                    // if > 1 hand is evaluated as highest, split the pot evenly between the players
252 11
253
                    $potTotal = $chipPot->chips()->total();
254 11
255
                    // split the pot between the number of players
256
                    $splitTotal = Chips::fromAmount(($potTotal->amount() / $evaluate->count()));
257
                    $evaluate->each(function (CardResults $result) use ($splitTotal) {
258
                        $result->hand()->player()->chipStack()->add($splitTotal);
259 1
                    });
260
261
                    $this->chipPots()->remove($chipPot);
262 1
                }
263
            })
264 1
        ;
265 1
    }
266
267 1
    /**
268
     * @param Player $actualPlayer
269 11
     *
270
     * @return bool
271 11
     */
272
    public function playerIsStillIn(PlayerContract $actualPlayer)
273
    {
274
        $playerCount = $this->playersStillIn()->filter->equals($actualPlayer)->count();
275
276
        return $playerCount === 1;
277
    }
278 1
279
    /**
280 1
     * @return PlayerContract
281
     */
282 1
    public function playerWithButton(): PlayerContract
283
    {
284
        return $this->table()->locatePlayerWithButton();
285
    }
286
287
    /**
288 7
     * @return PlayerContract
289
     */
290 7
    public function playerWithSmallBlind(): PlayerContract
291
    {
292
        if ($this->table()->playersSatDown()->count() === 2) {
293
            return $this->table()->playersSatDown()->get($this->table()->button());
294
        }
295
296 21
        return $this->table()->playersSatDown()->get($this->table()->button() + 1);
297
    }
298 21
299 5
    /**
300
     * @return PlayerContract
301
     */
302 16
    public function playerWithBigBlind(): PlayerContract
303
    {
304
        if ($this->table()->playersSatDown()->count() === 2) {
305
            $idx = $this->table()->button();
306
            $idx = ($idx === 1) ? $idx - 1 : $idx + 1;
307
            return $this->table()->playersSatDown()->get($idx);
308 4
        }
309
310 4
        return $this->table()->playersSatDown()->get($this->table()->button() + 2);
311 1
    }
312
313
    /**
314 3
     * @param PlayerContract $player
315
     */
316
    public function postSmallBlind(PlayerContract $player)
317
    {
318
        // Take chips from player
319
        $chips = $this->smallBlind();
320 34
321
        $this->postBlind($player, $chips);
322
323 34
        $this->actions()->push(new Action($player, Action::SMALL_BLIND, ['chips' => $this->smallBlind()]));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
324
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, LeftToAct::SMALL_BLIND);
325 34
    }
326
327 34
    /**
328 34
     * @param PlayerContract $player
329 34
     */
330
    public function postBigBlind(PlayerContract $player)
331
    {
332
        // Take chips from player
333
        $chips = $this->bigBlind();
334 34
335
        $this->postBlind($player, $chips);
336
337 34
        $this->actions()->push(new Action($player, Action::BIG_BLIND, ['chips' => $this->bigBlind()]));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
338
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, LeftToAct::BIG_BLIND);
339 34
    }
340
341 34
    /**
342 34
     * @return Chips
343 34
     */
344
    private function smallBlind(): Chips
345
    {
346
        return Chips::fromAmount($this->gameRules()->smallBlind()->amount());
347
    }
348 34
349
    /**
350 34
     * @return Chips
351
     */
352
    private function bigBlind(): Chips
353
    {
354
        return Chips::fromAmount($this->gameRules()->bigBlind()->amount());
355
    }
356 34
357
    /**
358 34
     * @return ChipPot
359
     */
360
    public function currentPot(): ChipPot
361
    {
362
        return $this->currentPot;
363
    }
364 14
365
    /**
366 14
     * @return ChipPotCollection
367
     */
368
    public function chipPots(): ChipPotCollection
369
    {
370
        return $this->chipPots;
371
    }
372 20
373
    /**
374 20
     * @param PlayerContract $player
375
     *
376
     * @return Chips
377
     */
378
    public function playerBetStack(PlayerContract $player): Chips
379
    {
380
        return $this->betStacks->findByPlayer($player);
381
    }
382 31
383
    /**
384 31
     * @param PlayerContract $player
385
     * @param Chips          $chips
386
     */
387
    private function postBlind(PlayerContract $player, $chips)
388
    {
389
        $player->chipStack()->subtract($chips);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
390
391 34
        // Add chips to player's table stack
392
        $this->betStacks->put($player->name(), $chips);
393 34
    }
394
395
    /**
396 34
     * @return PlayerContract|false
397 34
     */
398
    public function whosTurnIsIt()
399
    {
400
        $nextPlayer = $this->leftToAct()->getNextPlayer();
401
        if ($nextPlayer === null) {
402
            return false;
403
        }
404 2
405
        return $this->players()
406 2
            ->filter(function (PlayerContract $player) use ($nextPlayer) {
407
                return $player->name() === $nextPlayer['player'];
408 2
            })
409 1
            ->first()
410
        ;
411
    }
412 1
413
    /**
414
     * @return ChipPotCollection
415
     */
416
    public function collectChipTotal(): ChipPotCollection
417
    {
418 36
        $allInActionsThisRound = $this->leftToAct()->filter(function (array $value) {
419
            return $value['action'] === LeftToAct::ALLIN;
420 36
        });
421
422
        $orderedBetStacks = $this->betStacks()
423 36
            ->reject(function (Chips $chips, $playerName) {
424 36
                $foldedPlayer = $this->foldedPlayers()->findByName($playerName);
425
                if ($foldedPlayer) {
426
                    return true;
427
                }
428
429
                return false;
430 20
            })
431
            ->sortByChipAmount();
432
433 20
        if ($allInActionsThisRound->count() > 1 && $orderedBetStacks->unique()->count() > 1) {
434 20
            $orderedBetStacks->each(function (Chips $playerChips, $playerName) use ($orderedBetStacks) {
435
                $remainingStacks = $orderedBetStacks->filter(function (Chips $chips) {
436 20
                    return $chips->amount() !== 0;
437 6
                });
438
439 6
                $this->currentPot = ChipPot::create();
440 6
                $this->chipPots()->push($this->currentPot);
441 5
442
                $player = $this->players()->findByName($playerName);
443
                $allInAmount = Chips::fromAmount($orderedBetStacks->findByPlayer($player)->amount());
444 6
445 6
                $remainingStacks->each(function (Chips $chips, $playerName) use ($allInAmount, $orderedBetStacks) {
446 6
                    $player = $this->players()->findByName($playerName);
447
448
                    $stackChips = Chips::fromAmount($allInAmount->amount());
449
450 6
                    if (($chips->amount() - $stackChips->amount()) <= 0) {
451 6
                        $stackChips = Chips::fromAmount($chips->amount());
452
                    }
453 6
454 6
                    $chips->subtract($stackChips);
455
                    $this->currentPot->addChips($stackChips, $player);
0 ignored issues
show
It seems like $player defined by $this->players()->findByName($playerName) on line 446 can be null; however, Cysha\Casino\Holdem\Game\ChipPot::addChips() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
456 6
                    $orderedBetStacks->put($playerName, Chips::fromAmount($chips->amount()));
457 6
                });
458
            });
459
460 6
            // sort the pots so we get rid of any empty ones
461
            $this->chipPots = $this->chipPots
462 6
                ->filter(function (ChipPot $chipPot) {
463
                    return $chipPot->total()->amount() !== 0;
464 6
                })
465 6
                ->values();
466
467
            // grab anyone that folded
468 6
            $this->betStacks()
469 6
                ->filter(function (Chips $chips, $playerName) {
470 6
                    $foldedPlayer = $this->foldedPlayers()->findByName($playerName);
471 6
                    if ($foldedPlayer && $chips->amount() > 0) {
472 6
                        return true;
473
                    }
474
475 6
                    return false;
476
                })
477 6
                ->each(function (Chips $chips, $playerName) use ($orderedBetStacks) {
478 6
                    $player = $this->players()->findByName($playerName);
479 6
480
                    $stackChips = Chips::fromAmount($chips->amount());
481
482 6
                    $chips->subtract($stackChips);
483
                    $this->chipPots->get(0)->addChips($stackChips, $player);
484 6
                    $orderedBetStacks->put($playerName, Chips::fromAmount($chips->amount()));
485 6
                });
486 5
        } else {
487
            $this->betStacks()->each(function (Chips $chips, $playerName) {
488
                $this->currentPot()->addChips($chips, $this->players()->findByName($playerName));
0 ignored issues
show
It seems like $this->players()->findByName($playerName) can be null; however, addChips() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
489 6
            });
490 6
        }
491
492
        $this->resetBetStacks();
493 5
494
        return $this->chipPots();
495 5
    }
496
497 5
    /**
498 5
     * Deal the Flop.
499 5
     */
500 6
    public function dealFlop()
501
    {
502
        if ($this->dealer()->communityCards()->count() !== 0) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
503 14
            throw RoundException::flopHasBeenDealt();
504 14
        }
505
        if ($player = $this->whosTurnIsIt()) {
506
            throw RoundException::playerStillNeedsToAct($player);
507 20
        }
508
509 20
        $this->collectChipTotal();
510
511
        $seat = $this->table()->findSeat($this->playerWithSmallBlind());
512
        $this->resetPlayerList($seat);
513
514
        $this->dealer()->dealCommunityCards(3);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method dealCommunityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
515 17
        $this->actions()->push(new Action($this->dealer(), Action::DEALT_FLOP, [
0 ignored issues
show
$this->dealer() is of type object<Cysha\Casino\Game\Contracts\Dealer>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
516
            'communityCards' => $this->dealer()->communityCards()->only(range(0, 2)),
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
517 17
        ]));
518 1
    }
519
520 17
    /**
521 1
     * Deal the turn card.
522
     */
523
    public function dealTurn()
524 16
    {
525
        if ($this->dealer()->communityCards()->count() !== 3) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
526 16
            throw RoundException::turnHasBeenDealt();
527 16
        }
528 16
        if (($player = $this->whosTurnIsIt()) !== false) {
529 16
            throw RoundException::playerStillNeedsToAct($player);
530 16
        }
531
532
        $this->collectChipTotal();
533 16
534
        $seat = $this->table()->findSeat($this->playerWithSmallBlind());
535
        $this->resetPlayerList($seat);
536 16
537 16
        $this->dealer()->dealCommunityCards(1);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method dealCommunityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
538 16
        $this->actions()->push(new Action($this->dealer(), Action::DEALT_TURN, [
0 ignored issues
show
$this->dealer() is of type object<Cysha\Casino\Game\Contracts\Dealer>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
539 16
            'communityCards' => $this->dealer()->communityCards()->only(3),
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
540
        ]));
541
    }
542
543
    /**
544 14
     * Deal the river card.
545
     */
546 14
    public function dealRiver()
547 2
    {
548
        if ($this->dealer()->communityCards()->count() !== 4) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
549 13
            throw RoundException::riverHasBeenDealt();
550 1
        }
551
        if (($player = $this->whosTurnIsIt()) !== false) {
552
            throw RoundException::playerStillNeedsToAct($player);
553 12
        }
554 12
555
        $this->collectChipTotal();
556
557
        $seat = $this->table()->findSeat($this->playerWithSmallBlind());
558
        $this->resetPlayerList($seat);
559 11
560
        $this->dealer()->dealCommunityCards(1);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method dealCommunityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
561 11
        $this->actions()->push(new Action($this->dealer(), Action::DEALT_RIVER, [
0 ignored issues
show
$this->dealer() is of type object<Cysha\Casino\Game\Contracts\Dealer>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
562 2
            'communityCards' => $this->dealer()->communityCards()->only(4),
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Dealer as the method communityCards() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Dealer.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
563
        ]));
564 10
    }
565 1
566
    /**
567
     * @throws RoundException
568 9
     */
569 9
    public function checkPlayerTryingToAct(PlayerContract $player)
570
    {
571
        $actualPlayer = $this->whosTurnIsIt();
572
        if ($actualPlayer === false) {
573
            throw RoundException::noPlayerActionsNeeded();
574 12
        }
575
        if ($player !== $actualPlayer) {
576 12
            throw RoundException::playerTryingToActOutOfTurn($player, $actualPlayer);
577
        }
578 12
    }
579 12
580 12
    /**
581 12
     * @param PlayerContract $player
582 12
     *
583
     * @throws RoundException
584
     */
585 12
    public function playerCalls(PlayerContract $player)
586
    {
587
        $this->checkPlayerTryingToAct($player);
588 12
589 12
        $highestChipBet = $this->highestBet();
590
591
        // current highest bet - currentPlayersChipStack
592
        $amountLeftToBet = Chips::fromAmount($highestChipBet->amount() - $this->playerBetStack($player)->amount());
593
594 33
        $chipStackLeft = Chips::fromAmount($player->chipStack()->amount() - $amountLeftToBet->amount());
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
595
596 33
        if ($chipStackLeft->amount() <= 0) {
597 33
            $amountLeftToBet = Chips::fromAmount($player->chipStack()->amount());
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
598 1
            $chipStackLeft = Chips::zero();
599
        }
600 33
601 2
        $action = $chipStackLeft->amount() === 0 ? Action::ALLIN : Action::CALL;
602
        $this->actions->push(new Action($player, $action, ['chips' => $amountLeftToBet]));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
603 31
604
        $this->placeChipBet($player, $amountLeftToBet);
605
606
        $action = $chipStackLeft->amount() === 0 ? LeftToAct::ALLIN : LeftToAct::ACTIONED;
607
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, $action);
608
    }
609
610 22
    /**
611
     * @param PlayerContract $player
612 22
     * @param Chips          $chips
613
     *
614 22
     * @throws RoundException
615
     */
616
    public function playerRaises(PlayerContract $player, Chips $chips)
617 22
    {
618
        $this->checkPlayerTryingToAct($player);
619 22
620
        $highestChipBet = $this->highestBet();
621 22
        if ($chips->amount() < $highestChipBet->amount()) {
622 22
            throw RoundException::raiseNotHighEnough($chips, $highestChipBet);
623 22
        }
624
625
        $chipStackLeft = Chips::fromAmount($player->chipStack()->amount() - $chips->amount());
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
626
        if ($chipStackLeft->amount() === 0) {
627
            return $this->playerPushesAllIn($player, $chips);
0 ignored issues
show
The call to Round::playerPushesAllIn() has too many arguments starting with $chips.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
628
        }
629
630
        $betAmount = Chips::fromAmount($highestChipBet->amount() + $chips->amount());
631 4
632
        $this->actions->push(new Action($player, Action::RAISE, ['chips' => $betAmount]));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
633 4
        $this->placeChipBet($player, $betAmount);
634
635 4
        $action = $chipStackLeft->amount() === 0 ? LeftToAct::ALLIN : LeftToAct::AGGRESSIVELY_ACTIONED;
636
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, $action);
637 4
    }
638 3
639 3
    /**
640
     * @param PlayerContract $player
641
     *
642
     * @throws RoundException
643
     */
644
    public function playerFoldsHand(PlayerContract $player)
645
    {
646 14
        $this->checkPlayerTryingToAct($player);
647
648 14
        $this->actions()->push(new Action($player, Action::FOLD));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
649
650 13
        $this->foldedPlayers->push($player);
651
        $this->leftToAct = $this->leftToAct()->removePlayer($player);
652 13
    }
653 13
654 13
    /**
655
     * @param PlayerContract $player
656
     *
657
     * @throws RoundException
658
     */
659
    public function playerPushesAllIn(PlayerContract $player)
660
    {
661 14
        $this->checkPlayerTryingToAct($player);
662
663 14
        // got the players chipStack
664
        $chips = $player->chipStack();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
665
666 14
        // gotta create a new chip obj here cause of PHPs /awesome/ objRef ability :D
667
        $this->actions()->push(new Action($player, Action::ALLIN, ['chips' => Chips::fromAmount($chips->amount())]));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
668
669 14
        $this->placeChipBet($player, $chips);
670
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, LeftToAct::ALLIN);
671 14
    }
672 14
673 14
    /**
674
     * @param PlayerContract $player
675
     *
676
     * @throws RoundException
677
     */
678
    public function playerChecks(PlayerContract $player)
679
    {
680 16
        $this->checkPlayerTryingToAct($player);
681
682 16
        if ($this->playerBetStack($player)->amount() !== $this->betStacks()->max()->amount()) {
683
            throw RoundException::cantCheckWithBetActive();
684 15
        }
685 15
686 15
        $this->actions()->push(new Action($player, Action::CHECK));
0 ignored issues
show
$player is of type object<Cysha\Casino\Game\Contracts\Player>, but the function expects a object<Cysha\Casino\Game\Contracts\Name>.

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...
687
        $this->leftToAct = $this->leftToAct()->playerHasActioned($player, LeftToAct::ACTIONED);
688
    }
689
690
    /**
691 22
     * @return Chips
692
     */
693
    private function highestBet(): Chips
694 22
    {
695 22
        return Chips::fromAmount($this->betStacks()->max(function (Chips $chips) {
696
            return $chips->amount();
697
        }) ?? 0);
698
    }
699
700
    /**
701
     * @param PlayerContract $player
702 30
     * @param Chips          $chips
703
     */
704 30
    private function placeChipBet(PlayerContract $player, Chips $chips)
705 1
    {
706
        if ($player->chipStack()->amount() < $chips->amount()) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method chipStack() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
707
            throw RoundException::notEnoughChipsInChipStack($player, $chips);
708
        }
709 30
710
        // add the chips to the players tableStack first
711
        $this->playerBetStack($player)->add($chips);
712 30
713 30
        // then remove it off their actual stack
714
        $player->bet($chips);
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Cysha\Casino\Game\Contracts\Player as the method bet() does only exist in the following implementations of said interface: Cysha\Casino\Holdem\Game\Player.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
715
    }
716
717
    /**
718
     * Reset the chip stack for all players.
719
     */
720 50
    private function resetBetStacks()
721 50
    {
722 50
        $this->players()->each(function (PlayerContract $player) {
723 50
            $this->betStacks->put($player->name(), Chips::zero());
724
        });
725
    }
726
727
    /**
728 50
     * Reset the leftToAct collection.
729
     */
730 50
    private function setupLeftToAct()
731 4
    {
732
        if ($this->players()->count() === 2) {
733 4
            $this->leftToAct = $this->leftToAct()->setup($this->players());
734
735
            return;
736 46
        }
737 46
738 46
        $this->leftToAct = $this->leftToAct
739 46
            ->setup($this->players())
740
            ->resetPlayerListFromSeat($this->table()->button() + 1);
741
    }
742
743
    /**
744 1
     * @param PlayerContract $player
745
     */
746 1
    public function sitPlayerOut(PlayerContract $player)
747 1
    {
748 1
        $this->table()->sitPlayerOut($player);
749
        $this->leftToAct = $this->leftToAct()->removePlayer($player);
750
    }
751
752
    /**
753
     * @var int
754
     */
755
    public function resetPlayerList(int $seat)
756
    {
757
        $this->leftToAct = $this->leftToAct
758
            ->resetActions()
759
            ->sortBySeats()
760
            ->resetPlayerListFromSeat($seat);
761
    }
762
}
763