Skip to content

Commit

Permalink
Merge pull request #325 from EasyPost/phpstan
Browse files Browse the repository at this point in the history
phpstan
  • Loading branch information
Justintime50 authored Nov 30, 2023
2 parents a9b7ee5 + 593ea2a commit 6a08b4a
Show file tree
Hide file tree
Showing 59 changed files with 524 additions and 398 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Fixes a bug where the original filtering criteria of `all` calls wasn't passed along to `getNextPage` calls. Now, these are persisted via a `_params` key on response objects locally
- Removes the undocumented `createAndBuy` function from the `Batch` service. The proper usage is to create a batch first and buy it separately
- Renames `primaryOrSecondary` to `priority` to match the API name for the parameter
- Fix various bugs throughout the library

## v6.9.1 (2023-11-20)

Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ install: | update-examples-submodule
composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist

## lint - Lint the project
lint: codesniffer scan
lint: codesniffer phpstan scan

## lint-fix - Fix linting errors
lint-fix: codesniffer-fix

## phpstan - Scan for static analysis errors
phpstan:
composer phpstan

## release - Cuts a release for the project on GitHub (requires GitHub CLI)
# tag = The associated tag title of the release
release:
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@
"phpunit/phpunit": "^9",
"squizlabs/php_codesniffer": "^3.7",
"roave/security-advisories": "dev-latest",
"rregeer/phpunit-coverage-check": "^0.3.1"
"rregeer/phpunit-coverage-check": "^0.3.1",
"phpstan/phpstan": "^1.10"
},
"scripts": {
"coverage": "XDEBUG_MODE=coverage ./bin/phpunit --coverage-html clover.html --coverage-clover build/logs/clover.xml && ./bin/coverage-check build/logs/clover.xml 85 --only-percentage",
"fix": "./bin/phpcbf --standard=examples/style_guides/php/phpcs.xml lib test",
"lint": "./bin/phpcs --standard=examples/style_guides/php/phpcs.xml lib test",
"phpstan": "./bin/phpstan analyse --memory-limit 1G",
"scan": "composer update --dry-run roave/security-advisories",
"test": "./bin/phpunit"
},
Expand Down
2 changes: 2 additions & 0 deletions lib/EasyPost/Brand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

/**
* @package EasyPost
* @property string $id
* @property string $object
* @property string $background_color
* @property string $color
* @property string $logo
Expand Down
24 changes: 13 additions & 11 deletions lib/EasyPost/EasyPostClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@
*
* @package EasyPost
* @property AddressService $address
* @property ApiKeyService $apiKey
* @property ApiKeyService $apiKeys
* @property BatchService $batch
* @property BetaReferralCustomer $betaReferralCustomer
* @property BetaRateService $betaRate
* @property BetaReferralCustomerService $betaReferralCustomer
* @property BillingService $billing
* @property CarrierAccountService $carrierAccount
* @property CarrierMetadataService $carrierMetadata
* @property CustomsInfoService $customsInfo
* @property CustomsItemService $customsItem
* @property EndShipperService $endShipper
Expand All @@ -65,21 +67,21 @@
class EasyPostClient extends BaseService
{
// Client properties
private $apiKey;
private $timeout;
private $apiBase;
private $mockingUtility;
public $requestEvent;
public $responseEvent;
public $httpClient;
private string $apiKey;
private float $timeout;
private string $apiBase;
private ?object $mockingUtility;
public object $requestEvent;
public object $responseEvent;
public Client $httpClient;

/**
* Constructor for an EasyPostClient.
*
* @param string $apiKey
* @param float $timeout
* @param string $apiBase
* @param object $mockingUtility
* @param object|null $mockingUtility
*/
public function __construct(
string $apiKey,
Expand Down Expand Up @@ -110,8 +112,8 @@ public function __get(string $serviceName)
'address' => AddressService::class,
'apiKeys' => ApiKeyService::class,
'batch' => BatchService::class,
'betaReferralCustomer' => BetaReferralCustomerService::class,
'betaRate' => BetaRateService::class,
'betaReferralCustomer' => BetaReferralCustomerService::class,
'billing' => BillingService::class,
'carrierAccount' => CarrierAccountService::class,
'carrierMetadata' => CarrierMetadataService::class,
Expand Down
18 changes: 15 additions & 3 deletions lib/EasyPost/EasyPostObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@

class EasyPostObject implements \ArrayAccess, \Iterator
{
/**
* @var array<mixed>
*/
protected array $_values;

/**
* @var array<mixed>
*/
protected array $_immutableValues;

private mixed $_parent;
private mixed $_name;

Expand Down Expand Up @@ -41,6 +49,8 @@ public function __set(string $k, mixed $v): void
$current = $this;
$param = [$k => $v];

// TODO: Rework this when we fix (de)serialization
// @phpstan-ignore-next-line
while (true && $i < 99) {
if (!is_null($current->_parent)) {
$param = [$current->_name => $param];
Expand Down Expand Up @@ -75,6 +85,8 @@ public function __unset(string $k): void
$current = $this;
$param = [$k => null];

// TODO: Rework this when we fix (de)serialization
// @phpstan-ignore-next-line
while (true && $i < 99) {
if (!is_null($current->_parent)) {
$param = [$current->_name => $param];
Expand Down Expand Up @@ -107,7 +119,7 @@ public function __get(string $k): mixed
* Construct EasyPost objects from a response.
*
* @param EasyPostClient|null $client
* @param array $values
* @param array<mixed> $values
* @param string $class
* @return mixed
*/
Expand All @@ -123,7 +135,7 @@ public static function constructFrom(?EasyPostClient $client, array $values, str
* Convert each piece of an EasyPost object.
*
* @param EasyPostClient|null $client
* @param array $values
* @param array<mixed> $values
*/
public function convertEach(?EasyPostClient $client, array $values): void
{
Expand Down Expand Up @@ -259,7 +271,7 @@ public function __toString(): string
* Convert object to an array.
*
* @param bool|null $recursive
* @return array
* @return array<mixed>
*/
public function __toArray(?bool $recursive = false): array
{
Expand Down
34 changes: 19 additions & 15 deletions lib/EasyPost/Exception/Api/ApiException.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@
namespace EasyPost\Exception\Api;

use EasyPost\Exception\General\EasyPostException;
use EasyPost\FieldError;
use Exception;

/**
* @package EasyPost
* @property string $code
* @property FieldError[] $errors
* @property string|null $code
* @property FieldError[]|null $errors
* @property string $message
* @property string|null $httpBody
* @property int|null $httpStatus
* @property mixed $jsonBody
*/
class ApiException extends EasyPostException
{
public $code;
public $errors;
protected $message;
private $httpBody;
private $httpStatus;
private $jsonBody;
public $code; // @phpstan-ignore-line
public $errors; // @phpstan-ignore-line
protected $message; // @phpstan-ignore-line
private ?string $httpBody;
private ?int $httpStatus;
private mixed $jsonBody;

/**
* ApiException constructor.
Expand All @@ -30,24 +36,22 @@ public function __construct(string $message = '', ?int $httpStatus = null, ?stri
parent::__construct($message);
$this->httpStatus = $httpStatus;
$this->httpBody = $httpBody;
$this->errors = null;
$this->code = null;

try {
$this->jsonBody = isset($httpBody) ? json_decode($httpBody, true) : null;

// Setup `errors` property
// Set `errors` property
if (isset($this->jsonBody) && !empty($this->jsonBody['error']['errors'])) {
$this->errors = $this->jsonBody['error']['errors'];
} else {
$this->errors = null;
}

// Setup `code` property
// Set `code` property
if (isset($this->jsonBody) && !empty($this->jsonBody['error']['code'])) {
$this->code = $this->jsonBody['error']['code'];
} else {
$this->code = null;
}
} catch (\Exception $e) {
} catch (Exception $e) { // @phpstan-ignore-line
$this->jsonBody = null;
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/EasyPost/Exception/General/EasyPostException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace EasyPost\Exception\General;

/**
* @package EasyPost
* @param string $message
*/
class EasyPostException extends \Exception
{
/**
Expand Down
2 changes: 0 additions & 2 deletions lib/EasyPost/Exception/General/EndOfPaginationException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ class EndOfPaginationException extends \Exception
{
/**
* EndOfPaginationException constructor.
*
* @param string $message
*/
public function __construct()
{
Expand Down
13 changes: 11 additions & 2 deletions lib/EasyPost/Hook/EventHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@
*/
class EventHook
{
private $eventHandlers = [];
/**
* @var array<callable>
*/
private array $eventHandlers = [];

public function __invoke(...$args)
/**
* Fires when the class is invoked.
*
* @param array<callable> ...$args
* @return void
*/
public function __invoke(array ...$args): void
{
foreach ($this->eventHandlers as $eventHandler) {
$eventHandler(...$args);
Expand Down
22 changes: 12 additions & 10 deletions lib/EasyPost/Http/Requestor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use DateTimeZone;
use EasyPost\Constant\Constants;
use EasyPost\EasyPostClient;
use EasyPost\EasypostObject;
use EasyPost\EasyPostObject;
use EasyPost\Exception\Api\BadRequestException;
use EasyPost\Exception\Api\ForbiddenException;
use EasyPost\Exception\Api\GatewayTimeoutException;
Expand All @@ -23,6 +23,7 @@
use EasyPost\Exception\Api\TimeoutException;
use EasyPost\Exception\Api\UnauthorizedException;
use EasyPost\Exception\Api\UnknownApiException;
use Exception;

class Requestor
{
Expand Down Expand Up @@ -64,14 +65,14 @@ public static function utf8(mixed $value): string
* Encodes an EasyPost object and prepares the data for the request.
*
* @param mixed $data
* @return array|string
* @return array<mixed>|string
*/
private static function encodeObjects(mixed $data): array|string
{
if (is_null($data)) {
return [];
} elseif ($data instanceof EasypostObject) {
return ['id' => self::utf8($data->id)];
return ['id' => self::utf8($data->id)]; // @phpstan-ignore-line
} elseif ($data === true) {
return 'true';
} elseif ($data === false) {
Expand Down Expand Up @@ -109,9 +110,9 @@ public static function urlEncode(mixed $arr, ?string $prefix = null): string
continue;
}

if ($prefix && isset($k)) {
if (isset($prefix)) {
$k = $prefix . '[' . $k . ']';
} elseif ($prefix) {
} else {
$k = $prefix . '[]';
}

Expand Down Expand Up @@ -156,7 +157,7 @@ public static function request(
* @param string $url
* @param mixed $params
* @param bool $beta
* @return array
* @return array<mixed>
* @throws HttpException
* @throws TimeoutException
*/
Expand Down Expand Up @@ -223,6 +224,7 @@ private static function requestRaw(

// Guzzle does not have a native way of catching timeout exceptions...
// If we don't have a response at this point, it's likely due to a timeout.
// @phpstan-ignore-next-line
if (!isset($response)) {
throw new TimeoutException(sprintf(Constants::NO_RESPONSE_ERROR, 'EasyPost'));
}
Expand Down Expand Up @@ -259,7 +261,7 @@ public static function interpretResponse(string $httpBody, int $httpStatus): mix
{
try {
$response = json_decode($httpBody, true);
} catch (\Exception $e) {
} catch (Exception $e) { // @phpstan-ignore-line
throw new JsonException(
"Invalid response body from API: HTTP Status: ({$httpStatus}) {$httpBody}",
$httpStatus,
Expand All @@ -279,7 +281,7 @@ public static function interpretResponse(string $httpBody, int $httpStatus): mix
*
* @param string|null $httpBody
* @param int $httpStatus
* @param array $response
* @param array<mixed> $response
* @throws BadRequestException
* @throws GatewayTimeoutException
* @throws InternalServerException
Expand All @@ -295,7 +297,7 @@ public static function interpretResponse(string $httpBody, int $httpStatus): mix
* @throws UnauthorizedException
* @throws UnknownApiException
*/
public static function handleApiError(?string $httpBody, int $httpStatus, array $response)
public static function handleApiError(?string $httpBody, int $httpStatus, array $response): void
{
if (!is_array($response) || !isset($response['error'])) {
throw new JsonException(
Expand Down Expand Up @@ -363,7 +365,7 @@ public static function handleApiError(?string $httpBody, int $httpStatus, array
* Recursively traverses a JSON element to extract error messages and returns them as a comma-separated string.
*
* @param mixed $errorMessage
* @param array $messagesList
* @param array<string> $messagesList
* @return string
*/
private static function traverseJsonElement(mixed $errorMessage, array &$messagesList): string
Expand Down
4 changes: 2 additions & 2 deletions lib/EasyPost/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class Order extends EasyPostObject
*
* To exclude a carrier or service, prepend the string with `!`.
*
* @param array|null $carriers
* @param array|null $services
* @param array<string>|null $carriers
* @param array<string>|null $services
* @return Rate
*/
public function lowestRate(?array $carriers = [], ?array $services = []): Rate
Expand Down
4 changes: 2 additions & 2 deletions lib/EasyPost/Pickup.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class Pickup extends EasyPostObject
*
* To exclude a carrier or service, prepend the string with `!`.
*
* @param array|null $carriers
* @param array|null $services
* @param array<string>|null $carriers
* @param array<string>|null $services
* @return PickupRate
*/
public function lowestRate(?array $carriers = [], ?array $services = []): PickupRate
Expand Down
Loading

0 comments on commit 6a08b4a

Please sign in to comment.