From d8bc31e7e79d2e17a3a3024b69e5f09f138af1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Guzm=C3=A1n=20Maeso?= Date: Sat, 2 Mar 2024 10:51:21 +0100 Subject: [PATCH 1/2] feat: improve code quality with rector rules --- src/Auth/AccessTokenOnlineResponse.php | 15 ++---- src/Auth/AccessTokenOnlineUserInfo.php | 24 +++------ src/Auth/AccessTokenResponse.php | 6 +-- src/Auth/FileSessionStorage.php | 3 +- src/Auth/OAuth.php | 50 ++++++++++--------- src/Auth/OAuthCookie.php | 15 ++---- src/Auth/Scopes.php | 8 ++- src/Auth/Session.php | 3 +- src/Clients/Graphql.php | 23 +++++---- src/Clients/Http.php | 27 +++++----- src/Clients/PageInfo.php | 15 +++--- src/Clients/Rest.php | 9 ++-- src/Clients/RestResponse.php | 5 +- src/Context.php | 13 ++--- .../RestResourceRequestException.php | 2 +- src/Exception/ShopifyException.php | 3 +- src/Rest/Base.php | 9 ++-- src/Utils.php | 24 +++++---- src/Webhooks/Delivery/EventBridge.php | 2 +- src/Webhooks/Delivery/HttpDelivery.php | 3 +- src/Webhooks/Delivery/PubSub.php | 2 +- src/Webhooks/ProcessResponse.php | 6 +-- src/Webhooks/RegisterResponse.php | 3 +- src/Webhooks/Registry.php | 42 +++++++++------- tests/Auth/OAuthTest.php | 12 +++-- tests/Clients/GraphqlTest.php | 5 +- tests/Clients/HttpTest.php | 3 +- tests/Clients/RestTest.php | 3 +- tests/ContextTest.php | 17 ++++--- tests/HttpRequestMatcher.php | 23 +++------ tests/HttpResponseMatcher.php | 9 ++-- tests/LogMock.php | 9 ++-- tests/UtilsTest.php | 12 +++-- 33 files changed, 198 insertions(+), 207 deletions(-) diff --git a/src/Auth/AccessTokenOnlineResponse.php b/src/Auth/AccessTokenOnlineResponse.php index bc6d9c20..fc4ed079 100644 --- a/src/Auth/AccessTokenOnlineResponse.php +++ b/src/Auth/AccessTokenOnlineResponse.php @@ -6,16 +6,11 @@ final class AccessTokenOnlineResponse extends AccessTokenResponse { - /** @var string */ - protected $accessToken; - /** @var string */ - protected $scope; - /** @var int */ - private $expiresIn; - /** @var string */ - private $associatedUserScope; - /** @var AccessTokenOnlineUserInfo|null */ - private $associatedUser = null; + protected string $accessToken; + protected string $scope; + private readonly int $expiresIn; + private readonly string $associatedUserScope; + private readonly ?AccessTokenOnlineUserInfo $associatedUser; public function __construct( string $accessToken, diff --git a/src/Auth/AccessTokenOnlineUserInfo.php b/src/Auth/AccessTokenOnlineUserInfo.php index 25040863..53a6ab17 100644 --- a/src/Auth/AccessTokenOnlineUserInfo.php +++ b/src/Auth/AccessTokenOnlineUserInfo.php @@ -6,22 +6,14 @@ final class AccessTokenOnlineUserInfo { - /** @var int */ - private $id; - /** @var string */ - private $firstName; - /** @var string */ - private $lastName; - /** @var string */ - private $email; - /** @var bool */ - private $emailVerified; - /** @var bool */ - private $accountOwner; - /** @var string */ - private $locale; - /** @var bool */ - private $collaborator; + private readonly int $id; + private readonly string $firstName; + private readonly string $lastName; + private readonly string $email; + private readonly bool $emailVerified; + private readonly bool $accountOwner; + private readonly string $locale; + private readonly bool $collaborator; public function __construct( int $id, diff --git a/src/Auth/AccessTokenResponse.php b/src/Auth/AccessTokenResponse.php index 7095ab81..1ff9b3e8 100644 --- a/src/Auth/AccessTokenResponse.php +++ b/src/Auth/AccessTokenResponse.php @@ -6,10 +6,8 @@ class AccessTokenResponse { - /** @var string */ - protected $accessToken; - /** @var string */ - protected $scope; + protected string $accessToken; + protected string $scope; public function __construct( string $accessToken, diff --git a/src/Auth/FileSessionStorage.php b/src/Auth/FileSessionStorage.php index c62ed4fd..ed98d0cb 100644 --- a/src/Auth/FileSessionStorage.php +++ b/src/Auth/FileSessionStorage.php @@ -9,8 +9,7 @@ */ class FileSessionStorage implements SessionStorage { - /** @var string */ - private $path; + private readonly string $path; /** * Initializes FileSessionStorage object diff --git a/src/Auth/OAuth.php b/src/Auth/OAuth.php index 8ee417a3..a7ce696e 100644 --- a/src/Auth/OAuth.php +++ b/src/Auth/OAuth.php @@ -4,6 +4,10 @@ namespace Shopify\Auth; +use Shopify\Exception\PrivateAppException; +use Shopify\Exception\UninitializedContextException; +use Shopify\Exception\OAuthCookieNotFoundException; +use Psr\Http\Client\ClientExceptionInterface; use Shopify\Clients\Http; use Shopify\Clients\HttpHeaders; use Shopify\Clients\HttpResponse; @@ -37,10 +41,10 @@ class OAuth * @param null|callable $setCookieFunction An optional override for setting cookie in response * * @return string The URL for OAuth redirection - * @throws \Shopify\Exception\CookieSetException - * @throws \Shopify\Exception\PrivateAppException - * @throws \Shopify\Exception\SessionStorageException - * @throws \Shopify\Exception\UninitializedContextException + * @throws CookieSetException + * @throws PrivateAppException + * @throws SessionStorageException + * @throws UninitializedContextException */ public static function begin( string $shop, @@ -108,13 +112,13 @@ public static function begin( * @param null|callable $setCookieFunction An optional override for setting cookie in response. * * @return Session - * @throws \Shopify\Exception\HttpRequestException - * @throws \Shopify\Exception\InvalidOAuthException - * @throws \Shopify\Exception\OAuthCookieNotFoundException - * @throws \Shopify\Exception\OAuthSessionNotFoundException - * @throws \Shopify\Exception\PrivateAppException - * @throws \Shopify\Exception\SessionStorageException - * @throws \Shopify\Exception\UninitializedContextException + * @throws HttpRequestException + * @throws InvalidOAuthException + * @throws OAuthCookieNotFoundException + * @throws OAuthSessionNotFoundException + * @throws PrivateAppException + * @throws SessionStorageException + * @throws UninitializedContextException */ public static function callback(array $cookies, array $query, ?callable $setCookieFunction = null): Session { @@ -213,8 +217,8 @@ public static function getOfflineSessionId(string $shop): string * @param bool $isOnline Whether to load online or offline sessions * * @return string The ID of the current session - * @throws \Shopify\Exception\MissingArgumentException - * @throws \Shopify\Exception\CookieNotFoundException + * @throws MissingArgumentException + * @throws CookieNotFoundException */ public static function getCurrentSessionId(array $rawHeaders, array $cookies, bool $isOnline): string { @@ -226,13 +230,13 @@ public static function getCurrentSessionId(array $rawHeaders, array $cookies, bo throw new MissingArgumentException('Missing Authorization key in headers array'); } $auth = $headers->get('authorization'); - preg_match('/^Bearer (.+)$/', $auth, $matches); + preg_match('/^Bearer (.+)$/', (string) $auth, $matches); if (!$matches) { throw new MissingArgumentException('Missing Bearer token in authorization header'); } $jwtPayload = Utils::decodeSessionToken($matches[1]); - $shop = preg_replace('/^https:\/\//', '', $jwtPayload['dest']); + $shop = preg_replace('/^https:\/\//', '', (string) $jwtPayload['dest']); if ($isOnline) { $currentSessionId = self::getJwtSessionId($shop, $jwtPayload['sub']); } else { @@ -257,7 +261,7 @@ public static function getCurrentSessionId(array $rawHeaders, array $cookies, bo * @param array $cookies The $cookies param from `callback` * * @return string The ID of the current session - * @throws \Shopify\Exception\CookieNotFoundException + * @throws CookieNotFoundException */ private static function getCookieSessionId(array $cookies): string { @@ -266,7 +270,7 @@ private static function getCookieSessionId(array $cookies): string $sessionId = null; if ($signature && $cookieId) { - $expectedSignature = hash_hmac('sha256', $cookieId, Context::$API_SECRET_KEY); + $expectedSignature = hash_hmac('sha256', (string) $cookieId, Context::$API_SECRET_KEY); if ($signature === $expectedSignature) { $sessionId = $cookieId; @@ -333,7 +337,7 @@ private static function setCookieSessionId(?callable $setCookieFunction, $sessio * @param Session $session The current session * * @return bool - * @throws \Shopify\Exception\UninitializedContextException + * @throws UninitializedContextException */ private static function isCallbackQueryValid(array $query, Session $session): bool { @@ -344,7 +348,7 @@ private static function isCallbackQueryValid(array $query, Session $session): bo return ( ($code) && ($sanitizedShop && strcmp($session->getShop(), $sanitizedShop) === 0) && - ($state && strcmp($session->getState(), $state) === 0) && + ($state && strcmp($session->getState(), (string) $state) === 0) && Utils::validateHmac($query, Context::$API_SECRET_KEY) ); } @@ -356,7 +360,7 @@ private static function isCallbackQueryValid(array $query, Session $session): bo * @param Session $session The OAuth session * * @return AccessTokenResponse|AccessTokenOnlineResponse The access token exchanged for the OAuth code - * @throws \Shopify\Exception\HttpRequestException + * @throws HttpRequestException */ private static function fetchAccessToken( array $query, @@ -424,9 +428,9 @@ private static function buildAccessTokenResponse(array $body): AccessTokenRespon * @param Http $client * @param array $post The POST payload * - * @return \Shopify\Clients\HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @return HttpResponse + * @throws ClientExceptionInterface + * @throws UninitializedContextException * @codeCoverageIgnore */ public static function requestAccessToken(Http $client, array $post): HttpResponse diff --git a/src/Auth/OAuthCookie.php b/src/Auth/OAuthCookie.php index fa1f1366..9156e81c 100644 --- a/src/Auth/OAuthCookie.php +++ b/src/Auth/OAuthCookie.php @@ -9,16 +9,11 @@ */ class OAuthCookie { - /** @var string */ - private $value; - /** @var string */ - private $name; - /** @var int|null */ - private $expire = 0; - /** @var bool */ - private $secure = true; - /** @var bool */ - private $httpOnly = true; + private readonly string $value; + private readonly string $name; + private readonly ?int $expire; + private readonly bool $secure; + private readonly bool $httpOnly; public function __construct( string $value, diff --git a/src/Auth/Scopes.php b/src/Auth/Scopes.php index 5b8958e8..0498036b 100644 --- a/src/Auth/Scopes.php +++ b/src/Auth/Scopes.php @@ -8,10 +8,8 @@ final class Scopes { public const SCOPE_DELIMITER = ','; - /** @var array */ - private $compressedScopes; - /** @var array */ - private $expandedScopes; + private readonly array $compressedScopes; + private readonly array $expandedScopes; /** * @param string|array $scopes @@ -98,7 +96,7 @@ private function getImpliedScopes(array $scopes): array { $impliedScopes = []; foreach ($scopes as $scope) { - if (preg_match('/^(unauthenticated_)?write_(.*)$/', $scope, $matches)) { + if (preg_match('/^(unauthenticated_)?write_(.*)$/', (string) $scope, $matches)) { $impliedScopes[] = ($matches[1] ?? '') . "read_{$matches[2]}"; } } diff --git a/src/Auth/Session.php b/src/Auth/Session.php index 0462aecf..8d86d23d 100644 --- a/src/Auth/Session.php +++ b/src/Auth/Session.php @@ -4,6 +4,7 @@ namespace Shopify\Auth; +use Exception; use DateTime; use Shopify\Context; use Shopify\Utils; @@ -94,7 +95,7 @@ public function setScope(string $scope): void /** * @param string|int|DateTime $expires * - * @throws \Exception + * @throws Exception */ public function setExpires($expires): void { diff --git a/src/Clients/Graphql.php b/src/Clients/Graphql.php index 07926255..55a9978e 100644 --- a/src/Clients/Graphql.php +++ b/src/Clients/Graphql.php @@ -4,15 +4,16 @@ namespace Shopify\Clients; +use Shopify\Exception\HttpRequestException; +use Psr\Http\Client\ClientExceptionInterface; +use Shopify\Exception\UninitializedContextException; use Shopify\Context; use Shopify\Exception\MissingArgumentException; class Graphql { - /** @var Http */ - private $client; - /** @var string|null */ - protected $token; + private readonly Http $client; + protected ?string $token; /** * GraphQL Client constructor. @@ -20,7 +21,7 @@ class Graphql * @param string $domain * @param string|null $token * - * @throws \Shopify\Exception\MissingArgumentException + * @throws MissingArgumentException */ public function __construct( string $domain, @@ -42,8 +43,8 @@ public function __construct( * @param int|null $tries How many times to attempt the request * * @return HttpResponse - * @throws \Shopify\Exception\HttpRequestException - * @throws \Shopify\Exception\MissingArgumentException + * @throws HttpRequestException + * @throws MissingArgumentException */ public function query( $data, @@ -82,10 +83,10 @@ public function query( * @param array $extraHeaders Any extra headers to send along with the request * @param int|null $tries How many times to attempt the request * - * @return \Shopify\Clients\HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\MissingArgumentException - * @throws \Shopify\Exception\UninitializedContextException + * @return HttpResponse + * @throws ClientExceptionInterface + * @throws MissingArgumentException + * @throws UninitializedContextException */ public function proxy( string $data, diff --git a/src/Clients/Http.php b/src/Clients/Http.php index ee443a0a..9d33672d 100644 --- a/src/Clients/Http.php +++ b/src/Clients/Http.php @@ -4,6 +4,8 @@ namespace Shopify\Clients; +use Psr\Http\Client\ClientExceptionInterface; +use Shopify\Exception\UninitializedContextException; use Exception; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Uri; @@ -23,8 +25,7 @@ class Http private const RETRIABLE_STATUS_CODES = [429, 500]; private const DEPRECATION_ALERT_SECONDS = 60; - /** @var string */ - private $domain; + private readonly string $domain; public function __construct(string $domain) { @@ -40,8 +41,8 @@ public function __construct(string $domain) * @param int|null $tries How many times to attempt the request * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws UninitializedContextException */ public function get(string $path, array $headers = [], array $query = [], ?int $tries = null): HttpResponse { @@ -65,8 +66,8 @@ public function get(string $path, array $headers = [], array $query = [], ?int $ * @param string $dataType The data type to expect in the response * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws UninitializedContextException */ public function post( string $path, @@ -98,8 +99,8 @@ public function post( * @param string $dataType The data type to expect in the response * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws UninitializedContextException */ public function put( string $path, @@ -129,8 +130,8 @@ public function put( * @param int|null $tries How many times to attempt the request * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws UninitializedContextException */ public function delete(string $path, array $headers = [], array $query = [], ?int $tries = null): HttpResponse { @@ -155,8 +156,8 @@ public function delete(string $path, array $headers = [], array $query = [], ?in * @param string $dataType The data type of the request * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws UninitializedContextException */ protected function request( string $path, @@ -249,7 +250,7 @@ protected function getRequestPath(string $path): string * * @param string $url The URL that used a deprecated resource * @param string $reason The deprecation reason - * @throws \Shopify\Exception\UninitializedContextException + * @throws UninitializedContextException */ private function logApiDeprecation(string $url, string $reason): void { diff --git a/src/Clients/PageInfo.php b/src/Clients/PageInfo.php index 9d924355..cb91fb53 100644 --- a/src/Clients/PageInfo.php +++ b/src/Clients/PageInfo.php @@ -8,12 +8,9 @@ class PageInfo { private const LINK_HEADER_REGEXP = '/<([^<]+)>; rel="([^"]+)"/'; - /** @var array|null */ - private $fields; - /** @var string|null */ - private $previousPageUrl; - /** @var string|null */ - private $nextPageUrl; + private readonly ?array $fields; + private readonly ?string $previousPageUrl; + private readonly ?string $nextPageUrl; /** * PageInfo constructor. @@ -63,13 +60,13 @@ private static function parseFields(array $linkHeaderSegments): array $fields = []; foreach ($linkHeaderSegments as $segment) { $parsedUrl = []; - preg_match(self::LINK_HEADER_REGEXP, $segment, $parsedUrl); + preg_match(self::LINK_HEADER_REGEXP, (string) $segment, $parsedUrl); $linkUrl = $parsedUrl[1]; $queryParams = self::getQueryFromUrl($linkUrl); if (array_key_exists('fields', $queryParams)) { $linkFields = $queryParams['fields']; - $fields = explode(',', $linkFields); + $fields = explode(',', (string) $linkFields); } } return $fields; @@ -86,7 +83,7 @@ private static function parseUrls(array $linkHeaderSegments): array $nextUrl = null; foreach ($linkHeaderSegments as $url) { $parsedLink = []; - preg_match(self::LINK_HEADER_REGEXP, $url, $parsedLink); + preg_match(self::LINK_HEADER_REGEXP, (string) $url, $parsedLink); $linkRel = $parsedLink[2]; $linkUrl = $parsedLink[1]; diff --git a/src/Clients/Rest.php b/src/Clients/Rest.php index 8f707f0c..65435fe1 100644 --- a/src/Clients/Rest.php +++ b/src/Clients/Rest.php @@ -9,8 +9,7 @@ class Rest extends Http { - /** @var string */ - private $accessToken; + private readonly ?string $accessToken; /** * Rest Client constructor. @@ -18,7 +17,7 @@ class Rest extends Http * @param string $domain * @param string|null $accessToken * - * @throws \Shopify\Exception\MissingArgumentException + * @throws MissingArgumentException */ public function __construct(string $domain, ?string $accessToken = null) { @@ -71,9 +70,9 @@ protected function getRequestPath(string $path): string } /** - * @param \Shopify\Clients\HttpResponse $response + * @param HttpResponse $response * - * @return \Shopify\Clients\PageInfo|null + * @return PageInfo|null */ private function getPageInfo(HttpResponse $response): ?PageInfo { diff --git a/src/Clients/RestResponse.php b/src/Clients/RestResponse.php index fb2cc422..9d42f57d 100644 --- a/src/Clients/RestResponse.php +++ b/src/Clients/RestResponse.php @@ -6,8 +6,7 @@ class RestResponse extends HttpResponse { - /** @var PageInfo|null */ - private $pageInfo = null; + private readonly ?PageInfo $pageInfo; /** * {@inheritDoc} @@ -25,7 +24,7 @@ public function __construct( } /** - * @return \Shopify\Clients\PageInfo|null Pagination Information + * @return PageInfo|null Pagination Information */ public function getPageInfo(): ?PageInfo { diff --git a/src/Context.php b/src/Context.php index 03b1f38f..3f2669e0 100644 --- a/src/Context.php +++ b/src/Context.php @@ -4,6 +4,7 @@ namespace Shopify; +use Exception; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Shopify\Auth\Scopes; @@ -68,7 +69,7 @@ class Context * it * @param string[] $customShopDomains One or more regexps to use when validating domains * - * @throws \Shopify\Exception\MissingArgumentException + * @throws MissingArgumentException */ public static function initialize( string $apiKey, @@ -142,7 +143,7 @@ public static function initialize( /** * Throws exception if initialize() has not been called * - * @throws \Shopify\Exception\UninitializedContextException + * @throws UninitializedContextException */ public static function throwIfUninitialized(): void { @@ -159,7 +160,7 @@ public static function throwIfUninitialized(): void * * @param string $message Message to output with the exception * - * @throws \Shopify\Exception\PrivateAppException + * @throws PrivateAppException */ public static function throwIfPrivateApp(string $message): void { @@ -175,7 +176,7 @@ public static function throwIfPrivateApp(string $message): void * @param string $level One of the \Psr\Log\LogLevel::* consts, defaults to INFO * @param array $context Key/value pairs of contextual information supporting the log statement * - * @throws \Shopify\Exception\UninitializedContextException + * @throws UninitializedContextException */ public static function log(string $message, string $level = LogLevel::INFO, array $context = []): void { @@ -301,12 +302,12 @@ public static function logCritical(string $message, array $context = []): void * * @throws UninitializedContextException * @throws FeatureDeprecatedException - * @throws \Exception + * @throws Exception */ public static function logDeprecation(string $deprecatedFrom, string $message, array $context = []): void { if (!preg_match('#^\d+.\d+.\d+$#', $deprecatedFrom)) { - throw new \Exception(sprintf('Encountered an invalid version: "%s"', $deprecatedFrom)); + throw new Exception(sprintf('Encountered an invalid version: "%s"', $deprecatedFrom)); } $currentVersion = Utils::getVersion(); diff --git a/src/Exception/RestResourceRequestException.php b/src/Exception/RestResourceRequestException.php index e69221df..26bd2af5 100644 --- a/src/Exception/RestResourceRequestException.php +++ b/src/Exception/RestResourceRequestException.php @@ -6,7 +6,7 @@ class RestResourceRequestException extends ShopifyException { - private int $statusCode; + private readonly int $statusCode; public function __construct($message, $statusCode) { diff --git a/src/Exception/ShopifyException.php b/src/Exception/ShopifyException.php index 979e423d..16060212 100644 --- a/src/Exception/ShopifyException.php +++ b/src/Exception/ShopifyException.php @@ -4,6 +4,7 @@ namespace Shopify\Exception; -class ShopifyException extends \Exception +use Exception; +class ShopifyException extends Exception { } diff --git a/src/Rest/Base.php b/src/Rest/Base.php index 1c328836..b30e4c37 100644 --- a/src/Rest/Base.php +++ b/src/Rest/Base.php @@ -4,6 +4,7 @@ namespace Shopify\Rest; +use stdClass; use Shopify\Auth\Session; use Shopify\Clients\Rest; use Shopify\Clients\RestResponse; @@ -15,7 +16,7 @@ // When upgrading to PHP 8.2, consider using the AllowDynamicProperties attribute // https://stitcher.io/blog/deprecated-dynamic-properties-in-php-82#a-better-alternative -abstract class Base extends \stdClass +abstract class Base extends stdClass { public static string $API_VERSION; public static ?array $NEXT_PAGE_QUERY = null; @@ -133,13 +134,13 @@ public function toArray($saving = false): array protected static function getJsonBodyName(): string { $className = preg_replace("/^([A-z_0-9]+\\\)*([A-z_]+)/", "$2", static::class); - return strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $className)); + return strtolower((string) preg_replace("/([a-z])([A-Z])/", "$1_$2", (string) $className)); } protected static function getJsonResponseBodyNames(): array { $className = preg_replace("/^([A-z_0-9]+\\\)*([A-z_]+)/", "$2", static::class); - return [strtolower(preg_replace("/([a-z])([A-Z])/", "$1_$2", $className))]; + return [strtolower((string) preg_replace("/([a-z])([A-Z])/", "$1_$2", (string) $className))]; } /** @@ -258,7 +259,7 @@ private static function getPath( function ($matches) use ($urlIds) { return $urlIds[$matches[2]]; }, - $path["path"] + (string) $path["path"] ); } diff --git a/src/Utils.php b/src/Utils.php index d7c1dc6d..deaafa81 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -4,6 +4,10 @@ namespace Shopify; +use Shopify\Exception\UninitializedContextException; +use Shopify\Exception\CookieNotFoundException; +use Shopify\Exception\MissingArgumentException; +use Psr\Http\Client\ClientExceptionInterface; use Shopify\Context; use Shopify\Auth\OAuth; use Shopify\Auth\Session; @@ -53,7 +57,7 @@ public static function sanitizeShopDomain(string $shop, ?string $myshopifyDomain } $name = preg_replace("/\A(https?\:\/\/)/", '', $name); - if (preg_match("/\A[a-zA-Z0-9][a-zA-Z0-9\-]*\.{$allowedDomainsRegexp}\z/", $name)) { + if (preg_match("/\A[a-zA-Z0-9][a-zA-Z0-9\-]*\.{$allowedDomainsRegexp}\z/", (string) $name)) { return $name; } else { return null; @@ -140,7 +144,7 @@ public static function getQueryParams(string $url): array * @param string $referenceVersion The version to check * * @return bool - * @throws \Shopify\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ public static function isApiVersionCompatible(string $referenceVersion): bool { @@ -166,7 +170,7 @@ public static function isApiVersionCompatible(string $referenceVersion): bool * @param bool $includeExpired Optionally include expired sessions, defaults to false * * @return Session|null If exists, the most recent session - * @throws \Shopify\Exception\UninitializedContextException + * @throws UninitializedContextException */ public static function loadOfflineSession(string $shop, bool $includeExpired = false): ?Session { @@ -190,8 +194,8 @@ public static function loadOfflineSession(string $shop, bool $includeExpired = f * @param bool $isOnline Whether to load online or offline sessions * * @return Session|null The session or null if the session can't be found - * @throws \Shopify\Exception\CookieNotFoundException - * @throws \Shopify\Exception\MissingArgumentException + * @throws CookieNotFoundException + * @throws MissingArgumentException */ public static function loadCurrentSession(array $rawHeaders, array $cookies, bool $isOnline): ?Session { @@ -222,11 +226,11 @@ public static function decodeSessionToken(string $jwt): array * @param string $rawBody The raw HTTP request payload * * @return HttpResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\CookieNotFoundException - * @throws \Shopify\Exception\MissingArgumentException - * @throws \Shopify\Exception\SessionNotFoundException - * @throws \Shopify\Exception\UninitializedContextException + * @throws ClientExceptionInterface + * @throws CookieNotFoundException + * @throws MissingArgumentException + * @throws SessionNotFoundException + * @throws UninitializedContextException */ public static function graphqlProxy(array $rawHeaders, array $cookies, string $rawBody): HttpResponse { diff --git a/src/Webhooks/Delivery/EventBridge.php b/src/Webhooks/Delivery/EventBridge.php index b5bed04f..37c105a1 100644 --- a/src/Webhooks/Delivery/EventBridge.php +++ b/src/Webhooks/Delivery/EventBridge.php @@ -10,7 +10,7 @@ class EventBridge extends DeliveryMethod { /** - * @throws \Shopify\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ public function __construct() { diff --git a/src/Webhooks/Delivery/HttpDelivery.php b/src/Webhooks/Delivery/HttpDelivery.php index 8d4686d9..13319f39 100644 --- a/src/Webhooks/Delivery/HttpDelivery.php +++ b/src/Webhooks/Delivery/HttpDelivery.php @@ -2,6 +2,7 @@ namespace Shopify\Webhooks\Delivery; +use Shopify\Exception\InvalidArgumentException; use Shopify\Context; use Shopify\Utils; use Shopify\Webhooks\DeliveryMethod; @@ -22,7 +23,7 @@ public function getCallbackAddress(string $path): string * @param string $topic * * @return string - * @throws \Shopify\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ public function buildCheckQuery(string $topic): string { diff --git a/src/Webhooks/Delivery/PubSub.php b/src/Webhooks/Delivery/PubSub.php index 097195bc..5cacec28 100644 --- a/src/Webhooks/Delivery/PubSub.php +++ b/src/Webhooks/Delivery/PubSub.php @@ -10,7 +10,7 @@ class PubSub extends DeliveryMethod { /** - * @throws \Shopify\Exception\InvalidArgumentException + * @throws InvalidArgumentException */ public function __construct() { diff --git a/src/Webhooks/ProcessResponse.php b/src/Webhooks/ProcessResponse.php index 5e7848b8..acd07ed3 100644 --- a/src/Webhooks/ProcessResponse.php +++ b/src/Webhooks/ProcessResponse.php @@ -6,10 +6,8 @@ final class ProcessResponse { - /** @var bool */ - private $success; - /** @var string|null */ - private $errorMessage = null; + private readonly bool $success; + private readonly ?string $errorMessage; public function __construct(bool $success, ?string $errorMessage = null) { diff --git a/src/Webhooks/RegisterResponse.php b/src/Webhooks/RegisterResponse.php index 6b1c598f..5801e3c1 100644 --- a/src/Webhooks/RegisterResponse.php +++ b/src/Webhooks/RegisterResponse.php @@ -6,8 +6,7 @@ final class RegisterResponse { - /** @var bool */ - private $success; + private readonly bool $success; /** @var string|array|null */ private $body; diff --git a/src/Webhooks/Registry.php b/src/Webhooks/Registry.php index 0a6a5825..37fef0d5 100644 --- a/src/Webhooks/Registry.php +++ b/src/Webhooks/Registry.php @@ -4,6 +4,10 @@ namespace Shopify\Webhooks; +use Psr\Http\Client\ClientExceptionInterface; +use Shopify\Exception\UninitializedContextException; +use Shopify\Exception\HttpRequestException; +use Shopify\Exception\MissingArgumentException; use Exception; use Shopify\Clients\Graphql; use Shopify\Clients\HttpHeaders; @@ -62,11 +66,11 @@ public static function getHandler(string $topic): ?Handler * @param string $accessToken The access token to use for requests * @param string|null $deliveryMethod The delivery method for this webhook. Defaults to HTTP * - * @return \Shopify\Webhooks\RegisterResponse - * @throws \Psr\Http\Client\ClientExceptionInterface - * @throws \Shopify\Exception\InvalidArgumentException - * @throws \Shopify\Exception\UninitializedContextException - * @throws \Shopify\Exception\WebhookRegistrationException + * @return RegisterResponse + * @throws ClientExceptionInterface + * @throws InvalidArgumentException + * @throws UninitializedContextException + * @throws WebhookRegistrationException */ public static function register( string $path, @@ -126,8 +130,8 @@ public static function register( * * @return ProcessResponse * - * @throws \Shopify\Exception\InvalidWebhookException - * @throws \Shopify\Exception\MissingWebhookHandlerException + * @throws InvalidWebhookException + * @throws MissingWebhookHandlerException */ public static function process(array $rawHeaders, string $rawBody): ProcessResponse { @@ -165,16 +169,16 @@ public static function process(array $rawHeaders, string $rawBody): ProcessRespo * Checks if Shopify already has a callback set for this webhook via a GraphQL check, and checks if we need to * update our subscription if one exists. * - * @param \Shopify\Clients\Graphql $client + * @param Graphql $client * @param string $topic * @param string $callbackAddress - * @param \Shopify\Webhooks\DeliveryMethod $method + * @param DeliveryMethod $method * * @return array * - * @throws \Shopify\Exception\HttpRequestException - * @throws \Shopify\Exception\MissingArgumentException - * @throws \Shopify\Exception\WebhookRegistrationException + * @throws HttpRequestException + * @throws MissingArgumentException + * @throws WebhookRegistrationException */ private static function isWebhookRegistrationNeeded( Graphql $client, @@ -206,17 +210,17 @@ private static function isWebhookRegistrationNeeded( /** * Creates or updates a webhook subscription in Shopify by firing the appropriate GraphQL query. * - * @param \Shopify\Clients\Graphql $client + * @param Graphql $client * @param string $topic * @param string $callbackAddress - * @param \Shopify\Webhooks\DeliveryMethod $deliveryMethod + * @param DeliveryMethod $deliveryMethod * @param string|null $webhookId * * @return array * - * @throws \Shopify\Exception\HttpRequestException - * @throws \Shopify\Exception\MissingArgumentException - * @throws \Shopify\Exception\WebhookRegistrationException + * @throws HttpRequestException + * @throws MissingArgumentException + * @throws WebhookRegistrationException */ private static function sendRegisterRequest( Graphql $client, @@ -250,7 +254,7 @@ private static function sendRegisterRequest( * * @return HttpHeaders The parsed headers * - * @throws \Shopify\Exception\InvalidWebhookException + * @throws InvalidWebhookException */ private static function parseProcessHeaders(array $rawHeaders): HttpHeaders { @@ -277,7 +281,7 @@ private static function parseProcessHeaders(array $rawHeaders): HttpHeaders * @param string $rawBody The HTTP request body * @param string $hmac The HMAC from the HTTP headers * - * @throws \Shopify\Exception\InvalidWebhookException + * @throws InvalidWebhookException */ private static function validateProcessHmac(string $rawBody, string $hmac): void { diff --git a/tests/Auth/OAuthTest.php b/tests/Auth/OAuthTest.php index b105f6b0..529f2710 100644 --- a/tests/Auth/OAuthTest.php +++ b/tests/Auth/OAuthTest.php @@ -4,6 +4,8 @@ namespace ShopifyTest\Auth; +use Shopify\Exception\CookieNotFoundException; +use Exception; use Firebase\JWT\JWT; use Shopify\Auth\OAuth; use Shopify\Auth\Session; @@ -191,7 +193,7 @@ public function testCallbackFailsWithoutCookie() { $this->createTestSession(false); - $this->expectException(\Shopify\Exception\CookieNotFoundException::class); + $this->expectException(CookieNotFoundException::class); $this->expectExceptionMessage('Could not find the current session id in the cookies'); OAuth::callback([], []); } @@ -204,7 +206,7 @@ public function testCallbackFailsWithInvalidSignature() OAuth::SESSION_ID_SIG_COOKIE_NAME => "Not the right signature", OAuth::SESSION_ID_COOKIE_NAME => $this->oauthSessionId, ]; - $this->expectException(\Shopify\Exception\CookieNotFoundException::class); + $this->expectException(CookieNotFoundException::class); $this->expectExceptionMessage('Could not find the current session id in the cookies'); OAuth::callback($mockCookies, []); } @@ -550,7 +552,7 @@ function () { public function testGetCurrentSessionIdRaisesCookieNotFoundException() { Context::$IS_EMBEDDED_APP = false; - $this->expectException(\Shopify\Exception\CookieNotFoundException::class); + $this->expectException(CookieNotFoundException::class); $this->expectExceptionMessage('Could not find the current session id in the cookies'); OAuth::getCurrentSessionId([], [], true); @@ -629,8 +631,8 @@ private function createTestSession(bool $isOnline): Session * @param string $sessionId The id of the session * @param bool $isOnline Whether the expected session is online * - * @return \Shopify\Auth\Session - * @throws \Exception + * @return Session + * @throws Exception */ private function buildExpectedSession(string $sessionId, bool $isOnline = true): Session { diff --git a/tests/Clients/GraphqlTest.php b/tests/Clients/GraphqlTest.php index 613e952f..f31b2b5f 100644 --- a/tests/Clients/GraphqlTest.php +++ b/tests/Clients/GraphqlTest.php @@ -4,6 +4,7 @@ namespace ShopifyTest\Clients; +use Shopify\Exception\MissingArgumentException; use Shopify\Clients\Graphql; use Shopify\Context; use ShopifyTest\BaseTestCase; @@ -78,14 +79,14 @@ final class GraphqlTest extends BaseTestCase public function testPublicAppThrowsWithoutToken() { - $this->expectException(\Shopify\Exception\MissingArgumentException::class); + $this->expectException(MissingArgumentException::class); new Graphql('domain.myshopify.com'); } public function testThrowsIfQueryMissing() { $client = new Graphql('domain.myshopify.com', 'token'); - $this->expectException(\Shopify\Exception\MissingArgumentException::class); + $this->expectException(MissingArgumentException::class); $client->query(data: ''); } diff --git a/tests/Clients/HttpTest.php b/tests/Clients/HttpTest.php index c4a9c4d7..d2613223 100644 --- a/tests/Clients/HttpTest.php +++ b/tests/Clients/HttpTest.php @@ -4,6 +4,7 @@ namespace ShopifyTest\Clients; +use Shopify\Exception\HttpRequestException; use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LogLevel; @@ -301,7 +302,7 @@ public function testRequestThrowsErrorOnRequestFailure() ]); $client = new Http($this->domain); - $this->expectException(\Shopify\Exception\HttpRequestException::class); + $this->expectException(HttpRequestException::class); $client->get(path: 'test/path'); } diff --git a/tests/Clients/RestTest.php b/tests/Clients/RestTest.php index 29228027..95261b69 100644 --- a/tests/Clients/RestTest.php +++ b/tests/Clients/RestTest.php @@ -4,6 +4,7 @@ namespace ShopifyTest\Clients; +use Shopify\Exception\MissingArgumentException; use Shopify\Clients\Rest; use Shopify\Context; use ShopifyTest\BaseTestCase; @@ -23,7 +24,7 @@ class RestTest extends BaseTestCase public function testFailsToInstantiateWithoutAccessTokenForNonPrivateApps() { - $this->expectException(\Shopify\Exception\MissingArgumentException::class); + $this->expectException(MissingArgumentException::class); new Rest($this->domain); } diff --git a/tests/ContextTest.php b/tests/ContextTest.php index e2782057..160a336a 100644 --- a/tests/ContextTest.php +++ b/tests/ContextTest.php @@ -4,6 +4,11 @@ namespace ShopifyTest; +use Shopify\Exception\MissingArgumentException; +use Shopify\Exception\UninitializedContextException; +use Shopify\Exception\PrivateAppException; +use Exception; +use Shopify\Exception\InvalidArgumentException; use Psr\Log\LogLevel; use ReflectionClass; use Shopify\ApiVersion; @@ -57,7 +62,7 @@ public function testCanUpdateContext() public function testThrowsIfMissingArguments() { - $this->expectException(\Shopify\Exception\MissingArgumentException::class); + $this->expectException(MissingArgumentException::class); $this->expectExceptionMessage( 'Cannot initialize Shopify API Library. Missing values for: apiKey, apiSecretKey, scopes, hostName' ); @@ -79,7 +84,7 @@ public function testThrowsIfUninitialized() $reflectedIsInitialized->setAccessible(true); $reflectedIsInitialized->setValue(null, false); - $this->expectException(\Shopify\Exception\UninitializedContextException::class); + $this->expectException(UninitializedContextException::class); Context::throwIfUninitialized(); } @@ -94,7 +99,7 @@ public function testThrowsIfPrivateApp() apiVersion: 'unstable', isPrivateApp: true, ); - $this->expectException(\Shopify\Exception\PrivateAppException::class); + $this->expectException(PrivateAppException::class); $this->expectExceptionMessage('BOOOOOO'); Context::throwIfPrivateApp('BOOOOOO'); } @@ -193,7 +198,7 @@ public function testLogDeprecationFeatureDeprecatedExceptionText() public function testLogDeprecationVersionExceptionText() { - $this->expectException(\Exception::class); + $this->expectException(Exception::class); $this->expectExceptionMessage('Encountered an invalid version: "abc"'); Context::logDeprecation('abc', 'This message should not be logged.'); @@ -201,7 +206,7 @@ public function testLogDeprecationVersionExceptionText() public function testLogDeprecationExceptionTooComplexVersion() { - $this->expectException(\Exception::class); + $this->expectException(Exception::class); $this->expectExceptionMessage('Encountered an invalid version: "1.2.3-RC"'); Context::logDeprecation('1.2.3-RC', 'This message should not be logged.'); @@ -237,7 +242,7 @@ public function canSetHostSchemeProvider() public function testFailsOnInvalidHost() { - $this->expectException(\Shopify\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); Context::initialize( apiKey: 'ash', apiSecretKey: 'steffi', diff --git a/tests/HttpRequestMatcher.php b/tests/HttpRequestMatcher.php index 9c84b307..900f23ec 100644 --- a/tests/HttpRequestMatcher.php +++ b/tests/HttpRequestMatcher.php @@ -7,22 +7,15 @@ class HttpRequestMatcher extends Constraint { - /** @var string */ - private $url; - /** @var string */ - private $method; - /** @var string */ - private $userAgent; - /** @var array */ - private $headers = []; - /** @var string|null */ - private $body = null; - /** @var bool */ - private $allowOtherHeaders = true; + private readonly string|array $url; + private readonly string $method; + private readonly string $userAgent; + private readonly array $headers; + private readonly ?string $body; + private readonly bool $allowOtherHeaders; /** @var mixed */ private $bodyDiff; - /** @var bool */ - private $identicalBody; + private readonly bool $identicalBody; /** * HttpRequestMatcher constructor. @@ -85,7 +78,7 @@ private function matchHeadersWithoutUserAgent(RequestInterface $request): bool } foreach ($this->headers as $expectedHeader) { - $header = explode(':', $expectedHeader, 2); + $header = explode(':', (string) $expectedHeader, 2); $matchedHeaderValue = $request->getHeaderLine(trim($header[0])) === trim($header[1]); if (!($request->hasHeader(trim($header[0])) && $matchedHeaderValue)) { diff --git a/tests/HttpResponseMatcher.php b/tests/HttpResponseMatcher.php index 2b45c6dd..286a88ac 100644 --- a/tests/HttpResponseMatcher.php +++ b/tests/HttpResponseMatcher.php @@ -9,12 +9,9 @@ class HttpResponseMatcher extends Constraint { - /** @var int */ - private $statusCode = 200; - /** @var array */ - private $headers = []; - /** @var array|null */ - private $decodedBody = null; + private readonly int $statusCode; + private readonly array $headers; + private readonly ?array $decodedBody; /** * HttpResponseMatcher constructor. diff --git a/tests/LogMock.php b/tests/LogMock.php index e11fad06..64827814 100644 --- a/tests/LogMock.php +++ b/tests/LogMock.php @@ -2,6 +2,7 @@ namespace ShopifyTest; +use BadMethodCallException; /** * Used for testing purposes. * @@ -99,14 +100,14 @@ public function hasRecord($record, $level) public function hasRecordThatContains($message, $level) { return $this->hasRecordThatPasses(function ($rec) use ($message) { - return strpos($rec['message'], $message) !== false; + return strpos((string) $rec['message'], (string) $message) !== false; }, $level); } public function hasRecordThatMatches($regex, $level) { return $this->hasRecordThatPasses(function ($rec) use ($regex) { - return preg_match($regex, $rec['message']) > 0; + return preg_match($regex, (string) $rec['message']) > 0; }, $level); } @@ -125,7 +126,7 @@ public function hasRecordThatPasses(callable $predicate, $level) public function __call($method, $args) { - if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', (string) $method, $matches) > 0) { $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; $level = strtolower($matches[2]); if (method_exists($this, $genericMethod)) { @@ -133,7 +134,7 @@ public function __call($method, $args) return call_user_func_array([$this, $genericMethod], $args); } } - throw new \BadMethodCallException('Call to undefined method ' . $this::class . '::' . $method . '()'); + throw new BadMethodCallException('Call to undefined method ' . $this::class . '::' . $method . '()'); } public function reset() diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index b5e40d35..bfc3364b 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -4,6 +4,8 @@ namespace ShopifyTest; +use Shopify\Exception\InvalidArgumentException; +use Firebase\JWT\ExpiredException; use DateTime; use Firebase\JWT\JWT; use Shopify\Context; @@ -206,7 +208,7 @@ public function testIsApiVersionCompatible() $this->assertTrue(Utils::isApiVersionCompatible('2020-10')); $this->assertFalse(Utils::isApiVersionCompatible('2021-07')); - $this->expectException(\Shopify\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); $this->assertTrue(Utils::isApiVersionCompatible('not_a_version')); } @@ -244,7 +246,7 @@ public function testGetOfflineSessionReturnsNullIfSessionIsExpired() $offlineSession = new Session("offline_$this->domain", $this->domain, false, 'state'); $offlineSession->setScope(Context::$SCOPES->toString()); $offlineSession->setAccessToken('vatican_cameos'); - $offlineSession->setExpires(new \DateTime()); + $offlineSession->setExpires(new DateTime()); Context::$SESSION_STORAGE->storeSession($offlineSession); $this->assertNull(Utils::loadOfflineSession($this->domain, false)); @@ -305,7 +307,7 @@ public function testDecodeExpiredSessionTokenFails() $jwt = JWT::encode($payload, Context::$API_SECRET_KEY, 'HS256'); // Outside of leeway period - should throw an exception - $this->expectException(\Firebase\JWT\ExpiredException::class); + $this->expectException(ExpiredException::class); Utils::decodeSessionToken($jwt); } @@ -436,13 +438,13 @@ public function testGraphqlProxyFetchesDataWithCookies() public function testGetEmbeddedAppUrlThrowsOnEmptyHost() { - $this->expectException(\Shopify\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); Utils::getEmbeddedAppUrl(""); } public function testGetEmbeddedAppUrlThrowsOnInvalidHost() { - $this->expectException(\Shopify\Exception\InvalidArgumentException::class); + $this->expectException(InvalidArgumentException::class); Utils::getEmbeddedAppUrl("!@#$%^&*()"); } From cadaec91e37d36d5c33bdc477776490f7f913fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81ngel=20Guzm=C3=A1n=20Maeso?= Date: Sat, 2 Mar 2024 11:00:38 +0100 Subject: [PATCH 2/2] fix: lintian erros with PSR12 --- src/Exception/ShopifyException.php | 1 + tests/LogMock.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Exception/ShopifyException.php b/src/Exception/ShopifyException.php index 16060212..20381710 100644 --- a/src/Exception/ShopifyException.php +++ b/src/Exception/ShopifyException.php @@ -5,6 +5,7 @@ namespace Shopify\Exception; use Exception; + class ShopifyException extends Exception { } diff --git a/tests/LogMock.php b/tests/LogMock.php index 64827814..83523d1b 100644 --- a/tests/LogMock.php +++ b/tests/LogMock.php @@ -3,6 +3,7 @@ namespace ShopifyTest; use BadMethodCallException; + /** * Used for testing purposes. * @@ -126,7 +127,8 @@ public function hasRecordThatPasses(callable $predicate, $level) public function __call($method, $args) { - if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', (string) $method, $matches) > 0) { + $regex = '/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/'; + if (preg_match($regex, (string) $method, $matches) > 0) { $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; $level = strtolower($matches[2]); if (method_exists($this, $genericMethod)) {