Skip to content

Commit

Permalink
Merge pull request #851 from PennyDreadfulMTG/deck-fix
Browse files Browse the repository at this point in the history
Better 404s
  • Loading branch information
bakert authored Nov 19, 2024
2 parents f9d0919 + 1a45ff5 commit df5fc12
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 47 deletions.
8 changes: 7 additions & 1 deletion gatherling/Data/Db.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Gatherling\Exceptions\ConfigurationException;
use Gatherling\Exceptions\DatabaseException;
use Gatherling\Exceptions\MarshalException;
use Gatherling\Exceptions\NotFoundInDatabaseException;
use PDOException;
use PDOStatement;
use PDO;
Expand Down Expand Up @@ -180,7 +181,12 @@ public function select(string $sql, string $class, array $params = []): array
public function selectOnly(string $sql, string $class, array $params = []): Dto
{
$result = $this->select($sql, $class, $params);
if (count($result) !== 1) {
if (count($result) === 0) {
$type = str_replace('Dto', '', basename(str_replace('\\', '/', $class)));
$ids = array_values(array_filter($params, fn($v) => is_int($v) || is_string($v)));
throw new NotFoundInDatabaseException("Expected 1 row, got 0 for query: $sql with params " . json_encode($params), 0, null, $type, $ids);
}
if (count($result) > 1) {
throw new DatabaseException('Expected 1 row, got ' . count($result) . " for query: $sql with params " . json_encode($params));
}
return $result[0];
Expand Down
20 changes: 17 additions & 3 deletions gatherling/Exceptions/NotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,27 @@

class NotFoundException extends BadRequestException
{
public function __construct(string $message = "", int $code = 0, ?Throwable $previous = null)
{
/** @var list<int|string> */
public array $ids;

/** @param list<int|string|null> $ids */
public function __construct(
string $message,
int $code,
?Throwable $previous,
public string $type,
array $ids
) {
$this->ids = array_values(array_filter($ids, fn($id) => $id !== null));
parent::__construct($message, $code, $previous, 404);
}

public function getUserMessage(): string
{
return 'The requested resource was not found';
$msg = 'The requested ' . strtolower($this->type);
if ($this->ids !== []) {
$msg .= " (" . implode(', ', $this->ids) . ")";
}
return $msg . " was not found";
}
}
21 changes: 21 additions & 0 deletions gatherling/Exceptions/NotFoundInDatabaseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Gatherling\Exceptions;

use Throwable;

class NotFoundInDatabaseException extends DatabaseException
{
/** @param list<int|string> $ids */
public function __construct(
string $message,
int $code,
?Throwable $previous,
public string $type,
public array $ids
) {
parent::__construct($message, $code, $previous);
}
}
7 changes: 7 additions & 0 deletions gatherling/Helpers/ErrorHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use Gatherling\Exceptions\BadRequestException;
use Gatherling\Exceptions\GatherlingException;
use Gatherling\Exceptions\NotFoundException;
use Gatherling\Exceptions\NotFoundInDatabaseException;
use Gatherling\Views\Pages\Error;
use Throwable;

Expand All @@ -15,6 +17,11 @@ public function handle(Throwable $e): never
{
$requestId = Request::getRequestId();

if ($e instanceof NotFoundInDatabaseException) {
// BAKERT this is weak but it's a start
$e = new NotFoundException($e->getMessage(), $e->getCode(), $e, $e->type, $e->ids);
}

$message = (string)$e;

if ($e instanceof BadRequestException) {
Expand Down
2 changes: 1 addition & 1 deletion gatherling/Models/Deck.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public function save(): void
$affectedRows = db()->modify($sql, $params);
if ($affectedRows != 1) {
db()->rollback($transactionName);
throw new NotFoundException('Entry for ' . $this->playername . ' in ' . $this->eventname . ' not found');
throw new NotFoundException('Entry for ' . $this->playername . ' in ' . $this->eventname . ' not found', 0, null, 'Entry', [$this->playername, $this->eventname]);
}
} else {
$sql = 'UPDATE decks SET archetype = :archetype, name = :name, format = :format, tribe = :tribe, deck_colors = :deck_colors, notes = :notes WHERE id = :id';
Expand Down
2 changes: 1 addition & 1 deletion gatherling/Models/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function __construct(int $event_id, string $playername)
$params = ['event_id' => $event_id, 'player' => $playername];
$entry = db()->selectOnlyOrNull($sql, EntryDto::class, $params);
if ($entry == null) {
throw new NotFoundException('Entry for ' . $playername . ' in ' . $event_id . ' not found');
throw new NotFoundException('Entry for ' . $playername . ' in ' . $event_id . ' not found', 0, null, 'Entry', [$playername, $event_id]);
}
$this->medal = $entry->medal;
$this->drop_round = $entry->drop_round;
Expand Down
8 changes: 2 additions & 6 deletions gatherling/Models/Player.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ public function __construct(string $name)
FROM players
WHERE name = :name';
$params = ['name' => $name];
try {
$result = db()->selectOnly($sql, PlayerDto::class, $params);
} catch (DatabaseException $e) {
throw new NotFoundException("Player $name is not found.", 0, $e);
}
$result = db()->selectOnly($sql, PlayerDto::class, $params);
$this->name = $result->name;
$this->password = $result->password;
$this->host = $result->host;
Expand Down Expand Up @@ -240,7 +236,7 @@ public static function createByName(string $playername): self

$newPlayer = self::findByName($playername);
if (!$newPlayer) {
throw new NotFoundException("Failed to retrieve player we just created: {$playername}");
throw new NotFoundException("Failed to retrieve player we just created: {$playername}", 0, null, 'Player', [$playername]);
}
return $newPlayer;
}
Expand Down
6 changes: 3 additions & 3 deletions gatherling/Views/Components/MatchTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public function __construct(Player $player, string $selectedFormat, string $sele
}

$opp = $match->otherPlayer($player->name);
if (!$opp) {
throw new NotFoundException("Opponent not found for match {$match->id}");
if ($opp === null) {
throw new NotFoundException("Opponent not found for match {$match->id}", 0, null, 'Opponent', [$player->name]);
}
$res = 'D';
if ($match->playerWon($player->name)) {
Expand All @@ -43,7 +43,7 @@ public function __construct(Player $player, string $selectedFormat, string $sele

$event = $match->getEvent();
if (!$event->id) {
throw new NotFoundException("Event not found for match {$match->id}");
throw new NotFoundException("Event not found for match {$match->id}", 0, null, 'Event', [$match->id]);
}
$oppRating = $opponent->getRating('Composite', $event->start);
$oppDeck = $opponent->getDeckEvent($event->id);
Expand Down
21 changes: 12 additions & 9 deletions gatherling/Views/Components/Preregistration.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Gatherling\Models\Entry;
use Gatherling\Models\Event;
use Gatherling\Models\Player;
use InvalidArgumentException;

use function Safe\strtotime;

Expand All @@ -24,7 +25,7 @@ class Preregistration extends Component
public function __construct(Player $player)
{
if (!$player->name) {
throw new NotFoundException("Tried to display preregistration for a player with no name");
throw new NotFoundException("Tried to display preregistration for a player with no name", 0, null, 'Player', []);
}

$upcomingEvents = Event::getUpcomingEvents($player->name);
Expand Down Expand Up @@ -61,13 +62,14 @@ public function __construct(Player $player)
}
$eventLink = $targetUrl . '.php?event=' . rawurlencode($event->name);
$eventName = $event->name;
if (!$event->start || !strtotime($event->start)) {
throw new NotFoundException("Event start time not found for event {$event->name}");
$eventStart = strtotime($event->start);
if (!$eventStart) {
throw new InvalidArgumentException("Event start time not found for event {$event->name}");
}
$startingSoon = time() >= strtotime($event->start);
$startTime = new Time(strtotime($event->start), $now);
$startingSoon = time() >= $eventStart;
$startTime = new Time($eventStart, $now);
if (!$event->id) {
throw new NotFoundException("Event ID not found for event {$event->name}");
throw new InvalidArgumentException("Event ID not found for event {$event->name}");
}
$entry = new Entry($event->id, $player->name);

Expand Down Expand Up @@ -99,10 +101,11 @@ public function __construct(Player $player)
foreach ($availableEvents as $event) {
$eventReportLink = 'eventreport.php?event=' . rawurlencode($event->name);
$eventName = $event->name;
if (!$event->start || !strtotime($event->start)) {
throw new NotFoundException("Event start time not found for event {$event->name}");
$eventStart = strtotime($event->start);
if (!$eventStart) {
throw new InvalidArgumentException("Event start time not found for event {$event->name}");
}
$startTime = new Time(strtotime($event->start), time());
$startTime = new Time($eventStart, time());
$isFull = $event->isFull();
$requiresMtgo = $event->client == 1 && empty($player->mtgo_username);
$requiresMtga = $event->client == 2 && empty($player->mtga_username);
Expand Down
4 changes: 0 additions & 4 deletions gatherling/Views/Components/RecentDecksTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Gatherling\Models\Entry;
use Gatherling\Models\Event;
use Gatherling\Models\Player;
use Gatherling\Exceptions\NotFoundException;

use function Gatherling\Helpers\logger;

Expand All @@ -22,9 +21,6 @@ public function __construct(Player $player)
if (is_null($event)) {
return;
}
if (!$event->id || !$player->name || !$event->name) {
throw new NotFoundException("Seeming invalid event data for ({$event->id}|{$event->name}|{$player->name}");
}
$entry = new Entry($event->id, $player->name);
if ($entry->deck) {
$decks = $player->getRecentDecks(6);
Expand Down
4 changes: 2 additions & 2 deletions gatherling/Views/Components/SymbolTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SymbolTable extends Component
{
public int $sum;
/** @var array<array{color: string, num: int}> */
public array $symbols;
public array $colors = [];

public function __construct(Deck $deck)
{
Expand All @@ -22,7 +22,7 @@ public function __construct(Deck $deck)
if ($num == 0) {
continue;
}
$this->symbols[] = [
$this->colors[] = [
'color' => $color,
'num' => $num,
];
Expand Down
2 changes: 1 addition & 1 deletion gatherling/deck.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function main(): never
} elseif ($postMode === 'Update Deck') {
$deck = updateDeck($deck, post()->string('archetype'), post()->string('name'), post()->string('notes'), post()->string('contents', ''), post()->string('sideboard', ''));
if ($deck->id === null) {
throw new NotFoundException('Trying to update a deck with null id, which is not possible');
throw new InvalidArgumentException('Trying to update a deck with null id, which is not possible');
}
$deck = new Deck($deck->id); // had to do this to get the constructor to run, otherwise errors weren't loading
if ($deck->isValid()) {
Expand Down
2 changes: 1 addition & 1 deletion gatherling/eventreport.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
function main(): never
{
$eventName = get()->optionalString('event') ?? get()->optionalString('name');
if ($eventName && Event::exists($eventName)) {
if ($eventName !== null && Event::exists($eventName)) {
$event = new Event($eventName);
$notYetStarted = db()->bool('SELECT `start` > NOW() AS okay FROM events WHERE `name` = :name', ['name' => $event->name]);
$canPrereg = $event->prereg_allowed && $notYetStarted;
Expand Down
2 changes: 1 addition & 1 deletion gatherling/templates/partials/symbolTable.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{{#colors}}
<tr>
<td align="right" width="75">
<img alt="{{color}}" src="/images/mana{{color}}.png">
<img alt="{{color}}" src="styles/images/mana{{color}}.png">
&nbsp;
</td>
<td align="left">{{num}}</td>
Expand Down
14 changes: 0 additions & 14 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,6 @@
<code><![CDATA[$rows]]></code>
</PropertyNotSetInConstructor>
<RiskyTruthyFalsyComparison>
<code><![CDATA[!$opp]]></code>
<code><![CDATA[$losses]]></code>
<code><![CDATA[$wins]]></code>
</RiskyTruthyFalsyComparison>
Expand Down Expand Up @@ -1961,14 +1960,6 @@
<code><![CDATA[!$opp]]></code>
</RiskyTruthyFalsyComparison>
</file>
<file src="gatherling/Views/Components/SymbolTable.php">
<PropertyNotSetInConstructor>
<code><![CDATA[$symbols]]></code>
</PropertyNotSetInConstructor>
<UninitializedProperty>
<code><![CDATA[$this->symbols]]></code>
</UninitializedProperty>
</file>
<file src="gatherling/Views/Components/TimeZoneDropMenu.php">
<RiskyTruthyFalsyComparison>
<code><![CDATA[$selected]]></code>
Expand Down Expand Up @@ -2399,11 +2390,6 @@
<code><![CDATA[Player::loginName()]]></code>
</RiskyTruthyFalsyComparison>
</file>
<file src="gatherling/eventreport.php">
<RiskyTruthyFalsyComparison>
<code><![CDATA[$eventName]]></code>
</RiskyTruthyFalsyComparison>
</file>
<file src="gatherling/forgot.php">
<MixedArgument>
<code><![CDATA[$payload->name]]></code>
Expand Down

0 comments on commit df5fc12

Please sign in to comment.