This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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
|
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
}
}
![]() |
|||
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);
}
}
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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 ![]() |
|||
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);
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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);
![]() |
|||
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);
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
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 |
Let’s take a look at an example:
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
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: