diff --git a/src/Syntax/SteamApi/Client.php b/src/Syntax/SteamApi/Client.php index 98a017e..d9fd72f 100644 --- a/src/Syntax/SteamApi/Client.php +++ b/src/Syntax/SteamApi/Client.php @@ -15,6 +15,7 @@ use Syntax\SteamApi\Exceptions\ApiCallFailedException; use Syntax\SteamApi\Exceptions\ClassNotFoundException; use Syntax\SteamApi\Exceptions\InvalidApiKeyException; +use Syntax\SteamApi\Exceptions\UnrecognizedId; use Syntax\SteamApi\Steam\App; use Syntax\SteamApi\Steam\Group; use Syntax\SteamApi\Steam\Item; @@ -32,31 +33,31 @@ * @method App app() * @method Package package() * @method Group group() - * @method Item item($appId) + * @method Item item() */ class Client { use SteamId; - public $validFormats = ['json', 'xml', 'vdf']; + public array $validFormats = ['json', 'xml', 'vdf']; - protected $url = 'http://api.steampowered.com/'; + protected string $url = 'http://api.steampowered.com/'; - protected $client; + protected GuzzleClient $client; - protected $interface; + protected ?string $interface; - protected $method; + protected string $method; - protected $version = 'v0002'; + protected ?string $version = 'v0002'; - protected $apiKey; + protected string $apiKey; - protected $apiFormat = 'json'; + protected string $apiFormat = 'json'; protected $steamId; - protected $isService = false; + protected bool $isService = false; /** * @throws InvalidApiKeyException @@ -72,7 +73,7 @@ public function __construct() $this->setUpFormatted(); } - public function get() + public function get(): static { return $this; } @@ -199,7 +200,7 @@ protected function sendRequest(Request $request): stdClass $result = new stdClass(); $result->code = $response->getStatusCode(); - $result->body = json_decode((string) $response->getBody(true), null, 512, JSON_THROW_ON_ERROR); + $result->body = json_decode((string) $response->getBody(), null, 512, JSON_THROW_ON_ERROR); } catch (ClientException $e) { throw new ApiCallFailedException($e->getMessage(), $e->getResponse()->getStatusCode(), $e); } catch (ServerException $e) { @@ -208,6 +209,10 @@ protected function sendRequest(Request $request): stdClass throw new ApiCallFailedException($e->getMessage(), $e->getCode(), $e); } + if (empty((array)$result->body)) { + throw new ApiCallFailedException('Api call failed to complete due to an empty response.', $result->code); + } + // If all worked out, return the result return $result; } @@ -215,7 +220,7 @@ protected function sendRequest(Request $request): stdClass private function buildUrl($version = false): string { // Set up the basic url - $url = $this->url . $this->interface . '/' . $this->method . '/'; + $url = $this->url . ($this->interface ?? '') . '/' . $this->method . '/'; // If we have a version, add it if ($version) { @@ -227,6 +232,7 @@ private function buildUrl($version = false): string /** * @throws ClassNotFoundException + * @throws UnrecognizedId */ public function __call($name, $arguments) { @@ -288,7 +294,29 @@ protected function getServiceResponse($arguments) $arguments = json_encode($arguments, JSON_THROW_ON_ERROR); // Get the client - return $this->setUpService($arguments)->response; + $body = $this->setUpService($arguments); + + if (!isset($body->response) || empty((array)$body->response)) { + throw new ApiCallFailedException('Api call failed to complete due to an empty response.', 500); + } + + return $body->response; + } + + /** + * @throws ApiCallFailedException + * @throws GuzzleException + */ + protected function getClientResponse($arguments) + { + // Get the client + $body = $this->setUpClient($arguments); + + if (!isset($body->response) || empty((array)$body->response)) { + throw new ApiCallFailedException('Api call failed to complete due to an empty response.', 500); + } + + return $body->response; } /** @@ -310,10 +338,17 @@ protected function getApiKey(): string return $apiKey; } + /** + * @throws UnrecognizedId + */ private function convertSteamIdTo64(): void { if (is_array($this->steamId)) { - array_walk($this->steamId, function (&$id) { + array_walk( + /** + * @throws UnrecognizedId + */ + $this->steamId, function (&$id) { // Convert the id to all types and grab the 64 bit version $id = $this->convertToAll($id)->id64; }); diff --git a/src/Syntax/SteamApi/Steam/App.php b/src/Syntax/SteamApi/Steam/App.php index 207d445..67a130c 100644 --- a/src/Syntax/SteamApi/Steam/App.php +++ b/src/Syntax/SteamApi/Steam/App.php @@ -7,16 +7,18 @@ use Illuminate\Support\Collection; use Syntax\SteamApi\Containers\App as AppContainer; use Syntax\SteamApi\Exceptions\ApiCallFailedException; +use Syntax\SteamApi\Exceptions\InvalidApiKeyException; class App extends Client { /** - * @var bool + * @throws InvalidApiKeyException */ public function __construct() { parent::__construct(); + $this->url = 'http://store.steampowered.com/'; $this->interface = 'api'; } @@ -26,6 +28,8 @@ public function __construct() * @param null $country * @param null $language * @return Collection + * @throws ApiCallFailedException + * @throws GuzzleException */ public function appDetails($appIds, $country = null, $language = null): Collection { @@ -68,9 +72,7 @@ protected function convertToObjects($apps): Collection { $convertedApps = $this->convertGames($apps); - $apps = $this->sortObjects($convertedApps); - - return $apps; + return $this->sortObjects($convertedApps); } /** diff --git a/src/Syntax/SteamApi/Steam/Item.php b/src/Syntax/SteamApi/Steam/Item.php index cdb13e9..6f85365 100644 --- a/src/Syntax/SteamApi/Steam/Item.php +++ b/src/Syntax/SteamApi/Steam/Item.php @@ -14,6 +14,7 @@ class Item extends Client public function __construct() { parent::__construct(); + $this->url = 'http://store.steampowered.com/'; $this->isService = true; $this->interface = 'api'; diff --git a/src/Syntax/SteamApi/Steam/Package.php b/src/Syntax/SteamApi/Steam/Package.php index 73fb512..d256ce2 100644 --- a/src/Syntax/SteamApi/Steam/Package.php +++ b/src/Syntax/SteamApi/Steam/Package.php @@ -13,6 +13,7 @@ class Package extends Client public function __construct() { parent::__construct(); + $this->url = 'http://store.steampowered.com/'; $this->interface = 'api'; } diff --git a/src/Syntax/SteamApi/Steam/Player.php b/src/Syntax/SteamApi/Steam/Player.php index d594d18..a2e65f9 100644 --- a/src/Syntax/SteamApi/Steam/Player.php +++ b/src/Syntax/SteamApi/Steam/Player.php @@ -162,8 +162,9 @@ public function GetRecentlyPlayedGames($count = null): ?Collection * @throws ApiArgumentRequired * @throws GuzzleException * @throws \JsonException + * @deprecated - use ISteamUser.CheckAppOwnership */ - public function IsPlayingSharedGame($appIdPlaying) + public function IsPlayingSharedGame($appIdPlaying): string { // Set up the api details $this->setApiDetails(__FUNCTION__, 'v0001'); @@ -184,9 +185,7 @@ protected function convertToObjects($games): Collection { $convertedGames = $this->convertGames($games); - $games = $this->sortObjects($convertedGames); - - return $games; + return $this->sortObjects($convertedGames); } private function convertGames($games): Collection diff --git a/src/Syntax/SteamApi/Steam/User.php b/src/Syntax/SteamApi/Steam/User.php index ff25f43..ed97982 100644 --- a/src/Syntax/SteamApi/Steam/User.php +++ b/src/Syntax/SteamApi/Steam/User.php @@ -6,6 +6,7 @@ use InvalidArgumentException; use Syntax\SteamApi\Client; use Syntax\SteamApi\Containers\Player as PlayerContainer; +use Syntax\SteamApi\Exceptions\ApiArgumentRequired; use Syntax\SteamApi\Exceptions\ApiCallFailedException; use Syntax\SteamApi\Exceptions\UnrecognizedId; @@ -30,7 +31,11 @@ public function __construct($steamId) * * @return mixed * + * @throws ApiArgumentRequired + * @throws ApiCallFailedException + * @throws GuzzleException * @throws UnrecognizedId + * @throws \JsonException */ public function ResolveVanityURL($displayName = null): mixed { @@ -43,7 +48,7 @@ public function ResolveVanityURL($displayName = null): mixed $this->method = __FUNCTION__; $this->version = 'v0001'; - $results = $this->setUpClient(['vanityurl' => $displayName])->response; + $results = $this->getClientResponse(['vanityurl' => $displayName]); // Return the full steam ID object for the display name. return $results->message ?? $this->convertId($results->steamid); @@ -74,8 +79,12 @@ public function GetPlayerSummaries(string $steamId = null): array } /** + * @param $chunk + * @return array * @throws ApiCallFailedException * @throws GuzzleException + * @throws \JsonException + * @throws ApiArgumentRequired */ private function getChunkedPlayerSummaries($chunk): array { diff --git a/src/Syntax/SteamApi/SteamId.php b/src/Syntax/SteamApi/SteamId.php index 8dc088b..aa8dc90 100644 --- a/src/Syntax/SteamApi/SteamId.php +++ b/src/Syntax/SteamApi/SteamId.php @@ -10,21 +10,22 @@ trait SteamId private $rawValue; - private static $ID32 = 'id32'; + private static string $ID32 = 'id32'; - private static $ID64 = 'id64'; + private static string $ID64 = 'id64'; - private static $ID3 = 'id3'; + private static string $ID3 = 'id3'; - private static $id64Base = '76561197960265728'; + private static string $id64Base = '76561197960265728'; /** - * @param string|int $id + * @param int|string $id * @param string|null $format * * @return mixed + * @throws UnrecognizedId */ - public function convertId($id, $format = null) + public function convertId(int|string $id, string $format = null) { $this->convertToAll($id); @@ -46,7 +47,7 @@ public function convertId($id, $format = null) } } - protected function setUpFormatted() + protected function setUpFormatted(): void { $this->formatted = new \stdClass(); $this->formatted->{self::$ID32} = null; @@ -54,6 +55,9 @@ protected function setUpFormatted() $this->formatted->{self::$ID3} = null; } + /** + * @throws UnrecognizedId + */ private function convertToAll($id) { [$type, $matches] = $this->determineIDType($id); @@ -68,7 +72,7 @@ private function convertToAll($id) return $this->formatted; } - private function convertToID32() + private function convertToID32(): void { $z = bcdiv($this->rawValue, '2', 0); $y = bcmul($z, '2', 0); @@ -77,19 +81,22 @@ private function convertToID32() $this->formatted->{self::$ID32} = $formatted; } - private function convertToID64() + private function convertToID64(): void { $formatted = bcadd($this->rawValue, self::$id64Base, 0); $this->formatted->{self::$ID64} = $formatted; } - private function convertToID3() + private function convertToID3(): void { $formatted = "[U:1:$this->rawValue]"; $this->formatted->{self::$ID3} = $formatted; } - private function determineIDType($id) + /** + * @throws UnrecognizedId + */ + private function determineIDType($id): array { $id = trim((string) $id); @@ -113,7 +120,7 @@ private function determineIDType($id) * @param $type * @param $matches */ - private function getRawValue($id, $type, $matches) + private function getRawValue($id, $type, $matches): void { switch ($type) { case 'ID32': diff --git a/tests/BaseTester.php b/tests/BaseTester.php index 3b30d66..6b1fea9 100644 --- a/tests/BaseTester.php +++ b/tests/BaseTester.php @@ -6,25 +6,25 @@ class BaseTester extends TestCase { - protected $id32 = 'STEAM_1:1:31085444'; + protected string $id32 = 'STEAM_0:1:859819470'; - protected $id64 = 76561198022436617; + protected int $id64 = 76561199679904669; - protected $id3 = '[U:1:62170889]'; + protected string $id3 = '[U:1:1719638941]'; - protected $altId64 = 76561197979958413; + protected int $altId64 = 76561197979958413; - protected $appId = 620; + protected int $appId = 620; // Portal 2 - protected $packageId = 32848; + protected int $packageId = 469; // The Orange Box - protected $itemAppId = 440; + protected int $itemAppId = 5021; // Mann Co. Supply Crate Key - protected $groupId = 103582791429521412; + protected int $groupId = 103582791429521412; // Valve - protected $groupName = 'Valve'; + protected string $groupName = 'Valve'; - protected $steamClient; + protected Client $steamClient; protected function setUp(): void { @@ -118,7 +118,7 @@ protected function checkGroupProperties($group): void /** * @param $item */ - protected function checkItemProperties($item) + protected function checkItemProperties($item): void { $attributes = ['id', 'originalId', 'level', 'quality', 'quantity']; $this->assertObjectHasProperties($attributes, $item); @@ -127,7 +127,7 @@ protected function checkItemProperties($item) /** * @param $app */ - private function checkMainAppProperties($app) + private function checkMainAppProperties($app): void { $attributes = [ 'id', 'type', 'name', 'controllerSupport', 'description', 'about', 'fullgame', 'header', 'website', 'shortDescription' @@ -138,7 +138,7 @@ private function checkMainAppProperties($app) /** * @param $app */ - private function checkGeneralAppProperties($app) + private function checkGeneralAppProperties($app): void { $attributes = [ 'pcRequirements', 'legal', 'developers', 'publishers', 'price', 'platforms', 'metacritic', 'categories', 'genres', 'release', 'requiredAge', 'isFree', 'supportedLanguages', 'recommendations' @@ -149,7 +149,7 @@ private function checkGeneralAppProperties($app) /** * @param $app */ - private function checkNestedAppProperties($app) + private function checkNestedAppProperties($app): void { $this->assertObjectHasProperty('minimum', $app->pcRequirements); @@ -172,7 +172,7 @@ private function checkNestedAppProperties($app) /** * @param $package */ - private function checkNestedPackageProperties($package) + private function checkNestedPackageProperties($package): void { $attributes = ['currency', 'initial', 'final', 'discount_percent', 'individual']; $this->assertObjectHasProperties($attributes, $package->price); @@ -184,7 +184,7 @@ private function checkNestedPackageProperties($package) /** * @param $group */ - private function checkGroupMainSummaryProperties($group) + private function checkGroupMainSummaryProperties($group): void { $this->assertObjectHasProperty('groupID64', $group); $this->assertObjectHasProperty('groupDetails', $group); @@ -196,7 +196,7 @@ private function checkGroupMainSummaryProperties($group) /** * @param $group */ - private function checkGroupDetailProperties($group) + private function checkGroupDetailProperties($group): void { $this->assertObjectHasProperty('name', $group->groupDetails); $this->assertObjectHasProperty('url', $group->groupDetails); @@ -213,7 +213,7 @@ private function checkGroupDetailProperties($group) /** * @param $group */ - private function checkGroupMemberDetailsProperties($group) + private function checkGroupMemberDetailsProperties($group): void { $this->assertObjectHasProperty('count', $group->memberDetails); $this->assertObjectHasProperty('inChat', $group->memberDetails); @@ -224,7 +224,7 @@ private function checkGroupMemberDetailsProperties($group) /** * @param $group */ - private function checkGroupMemberProperties($group) + private function checkGroupMemberProperties($group): void { $startingMember = $group->members->get($group->startingMember); @@ -233,4 +233,15 @@ private function checkGroupMemberProperties($group) $this->assertObjectHasProperty('id3', $startingMember); } + protected function expectApiCallFailedException(string $message): void + { + $this->expectException(\Syntax\SteamApi\Exceptions\ApiCallFailedException::class); + $this->expectExceptionMessage($message); + } + + protected function expectEmptyResponseException(): void + { + $this->expectApiCallFailedException( 'Api call failed to complete due to an empty response'); + } + } diff --git a/tests/IdTest.php b/tests/IdTest.php index e506682..8657363 100644 --- a/tests/IdTest.php +++ b/tests/IdTest.php @@ -1,18 +1,22 @@ steamClient->convertId($this->id64); + $ids = $this->steamClient->convertId(76561198022436617); - $this->assertEquals($this->id32, $ids->id32); - $this->assertEquals($this->id64, $ids->id64); - $this->assertEquals($this->id3, $ids->id3); + $this->assertEquals('STEAM_1:1:31085444', $ids->id32); + $this->assertEquals(76561198022436617, $ids->id64); + $this->assertEquals('[U:1:62170889]', $ids->id3); } } diff --git a/tests/ItemTest.php b/tests/ItemTest.php index fcbf8df..0f7f269 100644 --- a/tests/ItemTest.php +++ b/tests/ItemTest.php @@ -8,7 +8,7 @@ class ItemTest extends BaseTester /** @test */ public function it_gets_items_for_an_app_by_user_id() { - $inventory = $this->steamClient->item()->GetPlayerItems($this->appId, $this->id64); + $inventory = $this->steamClient->item()->GetPlayerItems($this->appId, 76561198022436617); $this->assertCount(3, $inventory->items); diff --git a/tests/PlayerTest.php b/tests/PlayerTest.php index 6219ed7..ac9d36a 100644 --- a/tests/PlayerTest.php +++ b/tests/PlayerTest.php @@ -42,6 +42,8 @@ public function it_gets_the_badges_by_user_id() /** @test */ public function it_gets_the_badge_progress_by_user_id() { + $this->expectApiCallFailedException('Api call failed to complete due to an empty response'); + $progress = $this->steamClient->player($this->id64)->GetCommunityBadgeProgress(); $this->assertObjectHasProperty('quests', $progress); @@ -87,7 +89,7 @@ public function it_gets_the_owned_games_by_user_id_without_app_details() /** @test */ public function it_filters_the_owned_games_by_user_id() { - $games = $this->steamClient->player($this->id64)->GetOwnedGames(true, false, $this->appId); + $games = $this->steamClient->player($this->id64)->GetOwnedGames(true, false, 400); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $games); $this->assertInstanceOf(\Syntax\SteamApi\Containers\Game::class, $games->first()); @@ -134,6 +136,8 @@ public function it_gets_a_single_recently_played_game_by_user_id() /** @test */ public function it_checks_if_playing_a_shared_game_by_user_and_app_id() { + $this->expectEmptyResponseException(); + $playingSharedGame = $this->steamClient->player($this->id64)->IsPlayingSharedGame($this->appId); $this->assertNotNull($playingSharedGame); diff --git a/tests/UserStatsTest.php b/tests/UserStatsTest.php index 814f293..323227b 100644 --- a/tests/UserStatsTest.php +++ b/tests/UserStatsTest.php @@ -16,7 +16,7 @@ public function it_returns_null_when_there_are_no_achievements_for_a_game() /** @test */ public function it_gets_the_users_achievements_for_a_game() { - $achievements = $this->steamClient->userStats($this->id64)->GetPlayerAchievements(252950); + $achievements = $this->steamClient->userStats(76561198022436617)->GetPlayerAchievements(252950); $this->assertInstanceOf(\Syntax\SteamApi\Containers\Achievement::class, $achievements[0]); $this->checkAchievementProperties($achievements[0]); @@ -36,36 +36,32 @@ public function it_gets_the_global_achievement_percentage_for_a_game() /** @test */ public function it_gets_the_user_stats_for_a_game() { - $this->expectException(Syntax\SteamApi\Exceptions\ApiCallFailedException::class); + $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetUserStatsForGame($this->appId); - $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetUserStatsForGame(730); + $this->assertTrue(is_array($stats)); - // $this->assertTrue(is_array($stats)); - - // $attributes = ['name', 'achieved']; - // $this->assertObjectHasPropertys($attributes, $stats[0]); + $attributes = ['name', 'achieved']; + $this->assertObjectHasProperties($attributes, $stats[0]); } /** @test */ public function it_gets_all_the_user_stats_for_a_game() { - $this->expectException(Syntax\SteamApi\Exceptions\ApiCallFailedException::class); - - $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetUserStatsForGame(730, true); + $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetUserStatsForGame($this->appId, true); - // $this->assertTrue(is_object($stats)); + $this->assertTrue(is_object($stats)); - // $attributes = ['name', 'achieved']; - // $this->assertObjectHasPropertys($attributes, $stats->achievements[0]); + $attributes = ['name', 'achieved']; + $this->assertObjectHasProperties($attributes, $stats->achievements[0]); - // $attributes = ['name', 'value']; - // $this->assertObjectHasPropertys($attributes, $stats->stats[0]); + $attributes = ['name', 'value']; + $this->assertObjectHasProperties($attributes, $stats->stats[0]); } /** @test */ public function it_gets_all_the_stats_for_a_game() { - $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetSchemaForGame(730, true); + $stats = $this->steamClient->userStats(76_561_198_159_417_876)->GetSchemaForGame($this->appId); $this->assertTrue(is_object($stats)); diff --git a/tests/UserTest.php b/tests/UserTest.php index 40e0040..4a260b3 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -1,5 +1,7 @@ steamClient->user($this->id64)->ResolveVanityURL('stygiansabyss'); + $steamObject = $this->steamClient->user(76561198022436617)->ResolveVanityURL('stygiansabyss'); - $this->assertEquals($this->id64, $steamObject->id64); + $this->assertEquals(76561198022436617, $steamObject->id64); } /** @test */ @@ -138,7 +146,7 @@ public function it_gets_the_bans_for_the_supplied_user() $this->assertNotEquals($bans[0]->SteamId, $this->id64); } - private function checkPlayerClasses($friendsList) + private function checkPlayerClasses($friendsList): void { $this->assertInstanceOf(\Syntax\SteamApi\Containers\Player::class, $friendsList[0]); $this->assertInstanceOf(\Syntax\SteamApi\Containers\Id::class, $friendsList[0]->steamIds);