diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0ac614c..dcdc1e20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,9 +9,9 @@ jobs: fail-fast: false matrix: php-version: - - "7.4" - "8.0" - "8.1" + - "8.2" steps: - uses: actions/checkout@master diff --git a/CHANGELOG.md b/CHANGELOG.md index 02e336dc..0a0e8cfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## Unreleased +- [#262](https://github.com/Shopify/shopify-api-php/pull/262) ⚠️ [Breaking] Added support for PHP 8.2, and removed support for PHP 7.4 + ## v4.3.0 - 2023-04-12 - [#259](https://github.com/Shopify/shopify-api-php/pull/259) Added support for 2023-04 API version, updated auto-generated REST resources diff --git a/composer.json b/composer.json index cd3fc5e9..6209b247 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ } }, "require": { - "php": "^7.4 || ^8.0 || ^8.1", + "php": "^8.0 || ^8.1 || ^8.2", "ext-json": "*", "ramsey/uuid": "^4.1", "psr/log": "^1.1 || ^2.0 || ^3.0", diff --git a/docs/getting_started.md b/docs/getting_started.md index a16e94ed..96f583ec 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -29,14 +29,14 @@ You should call this method as early as possible in your application, as none of ```php Context::initialize( - $_ENV['SHOPIFY_API_KEY'], - $_ENV['SHOPIFY_API_SECRET'], - $_ENV['SHOPIFY_APP_SCOPES'], - $_ENV['SHOPIFY_APP_HOST_NAME'], - new FileSessionStorage('/tmp/php_sessions'), - '2021-04', - true, - false, + apiKey: $_ENV['SHOPIFY_API_KEY'], + apiSecretKey: $_ENV['SHOPIFY_API_SECRET'], + scopes: $_ENV['SHOPIFY_APP_SCOPES'], + hostName: $_ENV['SHOPIFY_APP_HOST_NAME'], + sessionStorage: new FileSessionStorage('/tmp/php_sessions'), + apiVersion: '2023-04', + isEmbeddedApp: true, + isPrivateApp: false, ); ``` diff --git a/docs/usage/graphql.md b/docs/usage/graphql.md index c51377c3..48b5f132 100644 --- a/docs/usage/graphql.md +++ b/docs/usage/graphql.md @@ -1,4 +1,5 @@ # Make a GraphQL API call + Once OAuth is complete, we can use the library's GraphQL client to make requests to the GraphQL Admin API. To do that, create an instance of `Graphql` using the current shop URL and, for non-private apps, the session `accessToken` in your app's endpoint. The GraphQL client's main method is `query`, which takes the following arguments and returns an `HttpResponse` object: @@ -10,6 +11,7 @@ The GraphQL client's main method is `query`, which takes the following arguments | `tries` | `int \| null` | No | `1` | How many times to attempt the request | Example use of `query` + ```php // Load current session to get `accessToken` $session = Shopify\Utils::loadCurrentSession($headers, $cookies, $isOnline); @@ -29,12 +31,13 @@ $queryString = <<query($queryString); +$response = $client->query(data: $queryString); // do something with the returned data ``` Example with variables + ```php // load current session and create GraphQL client like above example @@ -53,9 +56,9 @@ $variables = [ ["title" => "TARDIS"], ["descriptionHtml" => "Time and Relative Dimensions in Space"], ["productType" => "Time Lord technology"] - ] + ] ]; -$response = $client->query(['query' => $queryUsingVariables, 'variables' => $variables]); +$response = $client->query(data: ['query' => $queryUsingVariables, 'variables' => $variables]); // do something with the returned data ``` diff --git a/docs/usage/rest.md b/docs/usage/rest.md index 1007ddf3..1c68ad48 100644 --- a/docs/usage/rest.md +++ b/docs/usage/rest.md @@ -7,8 +7,9 @@ You can read our [REST Admin API](https://shopify.dev/docs/api/admin/getting-sta ## Making your first REST request REST Admin API endpoints are organized by [resource](https://shopify.dev/docs/api/admin/rest/reference#selecting-apis-for-your-app) . You'll need to use different API endpoints depending on the service that your app provides. There are two different ways of doing that with this library: -* [REST resources](#rest-resources) -* [REST client](#rest-client) + +- [REST resources](#rest-resources) +- [REST client](#rest-client) ### REST resources @@ -20,14 +21,14 @@ The resource classes will provide methods for all endpoints described in [the RE The REST client uses `get`, `post`, `put`, and `delete` requests to retrieve, create, update, and delete resources respectively. -| Parameter | Type | Required? | Default Value | Notes | -|:----------|:----------------|:---------:|:----------------:|:-------------------------------------------------| -| path | string | Yes | | The requested API endpoint path. This can be one of two formats: | -| body | string or array | No | null | Only `post`, and `put` methods can have body | -| headers | array | No | [] | Any extra headers to send along with the request | -| query | array | No | [] | Query parameters as an associative array | -| tries | int | No | null | How many times to attempt the request | -| dataType | No | No | `DATA_TYPE_JSON` | Only `post`, and `put` methods can have body | +| Parameter | Type | Required? | Default Value | Notes | +| :-------- | :-------------- | :-------: | :--------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| path | string | Yes | | The requested API endpoint path. This can be one of two formats: | +| body | string or array | No | null | Only `post`, and `put` methods can have body | +| headers | array | No | [] | Any extra headers to send along with the request | +| query | array | No | [] | Query parameters as an associative array | +| tries | int | No | null | How many times to attempt the request | +| dataType | No | No | `DATA_TYPE_JSON` | Only `post`, and `put` methods can have body | In the following example we will retrieve a list of products from a shop using `Shopify\Clients\Rest` class. @@ -35,7 +36,7 @@ In the following example we will retrieve a list of products from a shop using ` use Shopify\Clients\Rest; $client = new Rest($session->getShop(), $session->getAccessToken()); -$response = $client->get('products'); +$response = $client->get(path: 'products'); ``` This request returns an instance of `Shopify\Clients\RestResponse`. The response object includes response `statusCode`, `body`, `headers`, and pagination information. To access the response attributes you can use `getStatusCode`, `getBody` and `getHeaders` respectively. There is also a convenience method `getDecodedBody` that will give you the JSON decoded associative array of the response body. @@ -56,13 +57,13 @@ To get the next page. ```php $pageInfo = unserialize($serializedPageInfo); -$result = $client->get('products', [], $pageInfo->getNextPageQuery()); +$result = $client->get(path: 'products', query: $pageInfo->getNextPageQuery()); ``` PageInfo gives you some convenience methods to determine whether there is there are more pages. | method | Return type | Notes | -|:----------------------:|:-----------:|:-------------------------------| +| :--------------------: | :---------: | :----------------------------- | | hasNextPage() | bool | false if there is no more page | | hasPreviousPage() | bool | false if there is no more page | | getNextPageQuery() | array | Query to get the next page | diff --git a/docs/usage/storefront.md b/docs/usage/storefront.md index 12efefd9..6e9ae09d 100644 --- a/docs/usage/storefront.md +++ b/docs/usage/storefront.md @@ -39,7 +39,7 @@ $storefrontClient = new \Shopify\Clients\Storefront($shop, $storefrontAccessToke // Call query and pass your query as `data` $products = $storefrontClient->query( - <<id = $id; $this->shop = Utils::sanitizeShopDomain($shop); @@ -146,8 +146,7 @@ public function clone(string $newSessionId): Session */ public function isValid(): bool { - return ( - Context::$SCOPES->equals($this->scope) && + return (Context::$SCOPES->equals($this->scope) && $this->accessToken && (!$this->expires || ($this->expires > new DateTime())) ); diff --git a/src/Clients/Http.php b/src/Clients/Http.php index 9e719d23..a7035777 100644 --- a/src/Clients/Http.php +++ b/src/Clients/Http.php @@ -46,7 +46,13 @@ public function __construct(string $domain) */ public function get(string $path, array $headers = [], array $query = [], ?int $tries = null): HttpResponse { - return $this->request($path, self::METHOD_GET, null, $headers, $query, $tries); + return $this->request( + path: $path, + method: self::METHOD_GET, + headers: $headers, + query: $query, + tries: $tries, + ); } /** @@ -71,7 +77,15 @@ public function post( ?int $tries = null, string $dataType = self::DATA_TYPE_JSON ): HttpResponse { - return $this->request($path, self::METHOD_POST, $body, $headers, $query, $tries, $dataType); + return $this->request( + path: $path, + method: self::METHOD_POST, + body: $body, + headers: $headers, + query: $query, + tries: $tries, + dataType: $dataType, + ); } /** @@ -96,7 +110,15 @@ public function put( ?int $tries = null, string $dataType = self::DATA_TYPE_JSON ): HttpResponse { - return $this->request($path, self::METHOD_PUT, $body, $headers, $query, $tries, $dataType); + return $this->request( + path: $path, + method: self::METHOD_PUT, + body: $body, + headers: $headers, + query: $query, + tries: $tries, + dataType: $dataType, + ); } /** @@ -114,12 +136,11 @@ public function put( public function delete(string $path, array $headers = [], array $query = [], ?int $tries = null): HttpResponse { return $this->request( - $path, - self::METHOD_DELETE, - null, - $headers, - $query, - $tries, + path: $path, + method: self::METHOD_DELETE, + headers: $headers, + query: $query, + tries: $tries, ); } diff --git a/src/Rest/Base.php b/src/Rest/Base.php index 1afd8241..cc098a2f 100644 --- a/src/Rest/Base.php +++ b/src/Rest/Base.php @@ -13,7 +13,9 @@ use Shopify\Exception\RestResourceException; use Shopify\Exception\RestResourceRequestException; -abstract class Base +// 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 { public static string $API_VERSION; public static ?array $NEXT_PAGE_QUERY = null; @@ -178,16 +180,30 @@ protected static function request( $params = array_filter($params); switch ($httpMethod) { case "get": - $response = $client->get($path, [], $params); + $response = $client->get( + path: $path, + query: $params, + ); break; case "post": - $response = $client->post($path, $body, [], $params); + $response = $client->post( + path: $path, + body: $body, + query: $params, + ); break; case "put": - $response = $client->put($path, $body, [], $params); + $response = $client->put( + path: $path, + body: $body, + query: $params, + ); break; case "delete": - $response = $client->delete($path, [], $params); + $response = $client->delete( + path: $path, + query: $params, + ); break; } diff --git a/src/Webhooks/Registry.php b/src/Webhooks/Registry.php index 35dce130..e091201f 100644 --- a/src/Webhooks/Registry.php +++ b/src/Webhooks/Registry.php @@ -182,7 +182,7 @@ private static function isWebhookRegistrationNeeded( string $callbackAddress, DeliveryMethod $method ): array { - $checkResponse = $client->query($method->buildCheckQuery($topic)); + $checkResponse = $client->query(data: $method->buildCheckQuery($topic)); $checkStatusCode = $checkResponse->getStatusCode(); $checkBody = $checkResponse->getDecodedBody(); @@ -225,7 +225,9 @@ private static function sendRegisterRequest( DeliveryMethod $deliveryMethod, ?string $webhookId ): array { - $registerResponse = $client->query($deliveryMethod->buildRegisterQuery($topic, $callbackAddress, $webhookId)); + $registerResponse = $client->query( + data: $deliveryMethod->buildRegisterQuery($topic, $callbackAddress, $webhookId), + ); $statusCode = $registerResponse->getStatusCode(); $body = $registerResponse->getDecodedBody(); diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php index ad6f0abe..ac34ad5a 100644 --- a/tests/BaseTestCase.php +++ b/tests/BaseTestCase.php @@ -6,6 +6,7 @@ use GuzzleHttp\Psr7\Response; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Http\Client\ClientInterface; use Shopify\Clients\HttpClientFactory; use Shopify\Context; @@ -26,11 +27,11 @@ public function setUp(): void { // Initialize Context before each test Context::initialize( - 'ash', - 'steffi', - ['sleepy', 'kitty'], - 'www.my-friends-cats.com', - new MockSessionStorage(), + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: 'www.my-friends-cats.com', + sessionStorage: new MockSessionStorage(), ); Context::$RETRY_TIME_IN_SECONDS = 0; $this->version = require dirname(__FILE__) . '/../src/version.php'; @@ -87,7 +88,7 @@ public function mockTransportRequests(array $requests): void $request->identicalBody ); - $requestMatchers[] = [$matcher]; + $requestMatchers[] = $matcher; $newResponses[] = $request->error ? 'TEST EXCEPTION' : new Response( $request->response['statusCode'], @@ -96,12 +97,15 @@ public function mockTransportRequests(array $requests): void ); } + /** @var MockObject */ $client = $this->createMock(ClientInterface::class); $i = 0; $client->expects($this->exactly(count($requestMatchers))) ->method('sendRequest') - ->withConsecutive(...$requestMatchers) + ->with(self::callback(function ($request) use (&$i, $requestMatchers) { + return $requestMatchers[$i]->matches($request); + })) ->willReturnCallback( function () use (&$i, $newResponses) { $response = $newResponses[$i++]; @@ -113,6 +117,7 @@ function () use (&$i, $newResponses) { } ); + /** @var MockObject */ $factory = $this->createMock(HttpClientFactory::class); $factory->expects($this->any()) diff --git a/tests/Clients/GraphqlTest.php b/tests/Clients/GraphqlTest.php index 05346662..613e952f 100644 --- a/tests/Clients/GraphqlTest.php +++ b/tests/Clients/GraphqlTest.php @@ -22,9 +22,9 @@ final class GraphqlTest extends BaseTestCase /** @var array */ private $testQueryArray = [ - [ - 'shop' => 'name', - ], + [ + 'shop' => 'name', + ], ]; /** @var string */ @@ -86,7 +86,7 @@ public function testThrowsIfQueryMissing() { $client = new Graphql('domain.myshopify.com', 'token'); $this->expectException(\Shopify\Exception\MissingArgumentException::class); - $client->query(''); + $client->query(data: ''); } public function testCanQueryWithDataString() @@ -108,7 +108,7 @@ public function testCanQueryWithDataString() ) ]); - $response = $client->query($this->testQueryString); + $response = $client->query(data: $this->testQueryString); $this->assertThat( $response, new HttpResponseMatcher(200, [], json_decode($this->querySuccessResponse, true)) @@ -134,7 +134,7 @@ public function testCanQueryWithDataArray() ) ]); - $response = $client->query($this->testQueryArray); + $response = $client->query(data: $this->testQueryArray); $this->assertThat( $response, new HttpResponseMatcher(200, [], json_decode($this->querySuccessResponse, true)) @@ -161,7 +161,7 @@ public function testCanQueryWithVariables() ) ]); - $response = $client->query($query); + $response = $client->query(data: $query); $this->assertThat( $response, @@ -190,7 +190,7 @@ public function testCanQueryWithExtraHeaders() ) ]); - $response = $client->query($this->testQueryString, [], $extraHeaders); + $response = $client->query(data: $this->testQueryString, extraHeaders: $extraHeaders); $this->assertThat( $response, new HttpResponseMatcher(200, [], json_decode($this->querySuccessResponse, true)) @@ -227,7 +227,7 @@ public function testProxyForwardsBodyAsJsonType() ] ); - $response = $client->proxy($queryToProxy, $extraHeaders); + $response = $client->proxy(data: $queryToProxy, extraHeaders: $extraHeaders); $this->assertThat( $response, new HttpResponseMatcher(200, [], json_decode($this->querySuccessResponse, true)) diff --git a/tests/Clients/HttpTest.php b/tests/Clients/HttpTest.php index 06d09f1a..2b6a2fa6 100644 --- a/tests/Clients/HttpTest.php +++ b/tests/Clients/HttpTest.php @@ -44,7 +44,7 @@ public function testGetRequestWithoutQuery() ]); $client = new Http($this->domain); - $response = $client->get('test/path', $headers); + $response = $client->get(path: 'test/path', headers: $headers); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -65,7 +65,7 @@ public function testGetRequest() ]); $client = new Http($this->domain); - $response = $client->get('test/path', $headers, ["path" => "some_path"]); + $response = $client->get(path: 'test/path', headers: $headers, query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -87,9 +87,9 @@ public function testGetRequestWithArrayInQuery() $client = new Http($this->domain); $response = $client->get( - 'test/path', - $headers, - ["array" => ["value"], "hash" => ["key1" => "value1", "key2" => "value2"]] + path: 'test/path', + headers: $headers, + query: ["array" => ["value"], "hash" => ["key1" => "value1", "key2" => "value2"]] ); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -121,7 +121,12 @@ public function testPostRequest() $client = new Http($this->domain); - $response = $client->post('test/path', $this->product1, $headers, ["path" => "some_path"]); + $response = $client->post( + path: 'test/path', + body: $this->product1, + headers: $headers, + query: ["path" => "some_path"], + ); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -153,7 +158,12 @@ public function testPutRequest() $client = new Http($this->domain); - $response = $client->put('test/path', $this->product1, $headers, ["path" => "some_path"]); + $response = $client->put( + path: 'test/path', + body: $this->product1, + headers: $headers, + query: ["path" => "some_path"], + ); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -176,7 +186,7 @@ public function testDeleteRequest() $client = new Http($this->domain); - $response = $client->delete('test/path', $headers, ["path" => "some_path"]); + $response = $client->delete(path: 'test/path', headers: $headers, query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -203,7 +213,7 @@ public function testPostWithStringBody() $client = new Http($this->domain); - $response = $client->post('test/path', $body); + $response = $client->post(path: 'test/path', body: $body); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -223,7 +233,7 @@ public function testUserAgent() ]); $client = new Http($this->domain); - $client->get('test/path'); + $client->get(path: 'test/path'); $this->mockTransportRequests([ new MockRequest( @@ -238,7 +248,7 @@ public function testUserAgent() ), ]); - $client->get('test/path', ['User-Agent' => "Extra user agent"]); + $client->get(path: 'test/path', headers: ['User-Agent' => "Extra user agent"]); Context::$USER_AGENT_PREFIX = 'Test default user agent'; @@ -255,7 +265,7 @@ public function testUserAgent() ), ]); - $client->get('test/path'); + $client->get(path: 'test/path'); $userAgent = "^Extra user agent | Test default user agent | Shopify Admin API Library for PHP v$this->version$"; $this->mockTransportRequests([ @@ -271,7 +281,7 @@ public function testUserAgent() ), ]); - $client->get('test/path', ['User-Agent' => "Extra user agent"]); + $client->get(path: 'test/path', headers: ['User-Agent' => "Extra user agent"]); } public function testRequestThrowsErrorOnRequestFailure() @@ -291,7 +301,7 @@ public function testRequestThrowsErrorOnRequestFailure() $client = new Http($this->domain); $this->expectException(\Shopify\Exception\HttpRequestException::class); - $client->get('test/path'); + $client->get(path: 'test/path'); } public function testRetryAfterCanBeFloat() @@ -319,7 +329,7 @@ public function testRetryAfterCanBeFloat() $client = new Http($this->domain); - $response = $client->get('test/path', [], [], 2); + $response = $client->get(path: 'test/path', tries: 2); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -358,7 +368,7 @@ public function testRetryLogicForAllRetriableCodes() $client = new Http($this->domain); - $response = $client->get('test/path', [], [], 3); + $response = $client->get(path: 'test/path', tries: 3); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -397,7 +407,7 @@ public function testRetryStopsAfterReachingTheLimit() $client = new Http($this->domain); - $response = $client->get('test/path', [], [], 3); + $response = $client->get(path: 'test/path', tries: 3); $this->assertThat($response, new HttpResponseMatcher(500, ['X-Is-Last-Test-Request' => [true]])); } @@ -425,7 +435,7 @@ public function testRetryStopsOnNonRetriableError() $client = new Http($this->domain); - $response = $client->get('test/path', [], [], 10); + $response = $client->get(path: 'test/path', tries: 10); $this->assertThat($response, new HttpResponseMatcher(400, ['X-Is-Last-Test-Request' => [true]])); } diff --git a/tests/Clients/RestTest.php b/tests/Clients/RestTest.php index 600e2e9c..29228027 100644 --- a/tests/Clients/RestTest.php +++ b/tests/Clients/RestTest.php @@ -57,7 +57,7 @@ public function testPrivateAppsUseApiSecretKeyAsAccessToken() ), ]); - $response = $client->get('products', $headers); + $response = $client->get(path: 'products', headers: $headers); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -80,7 +80,7 @@ public function testCanMakeGetRequest() ), ]); - $response = $client->get('products', $headers); + $response = $client->get(path: 'products', headers: $headers); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -103,7 +103,7 @@ public function testAllowsFullPaths() ), ]); - $response = $client->get('/admin/custom_path', $headers); + $response = $client->get(path: '/admin/custom_path', headers: $headers); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -124,7 +124,7 @@ public function testCanMakeGetRequestWithPathInQuery() ), ]); - $response = $client->get('products', [], ["path" => "some_path"]); + $response = $client->get(path: 'products', query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -157,7 +157,7 @@ public function testCanMakePostRequestWithJsonData() ), ]); - $response = $client->post('products', $postData); + $response = $client->post(path: 'products', body: $postData); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -190,7 +190,7 @@ public function testCanMakePostRequestWithJsonDataAndPathInQuery() ), ]); - $response = $client->post('products', $postData, [], ["path" => "some_path"]); + $response = $client->post(path: 'products', body: $postData, query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -223,7 +223,7 @@ public function testCanMakePutRequestWithJsonData() ), ]); - $response = $client->put('products/123', $postData, [], ["path" => "some_path"]); + $response = $client->put(path: 'products/123', body: $postData, query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -246,7 +246,7 @@ public function testCanMakeDeleteRequest() ), ]); - $response = $client->delete('products', $headers, ["path" => "some_path"]); + $response = $client->delete(path: 'products', headers: $headers, query: ["path" => "some_path"]); $this->assertThat($response, new HttpResponseMatcher(200, [], $this->successResponse)); } @@ -299,23 +299,23 @@ public function testCanRequestNextAndPreviousPagesUntilTheyRunOut() $client = new Rest($this->domain, 'dummy-token'); /** @var RestResponse */ - $response = $client->get('products', [], ["limit" => "10", "fields" => 'test1,test2']); + $response = $client->get(path: 'products', query: ["limit" => "10", "fields" => 'test1,test2']); $this->assertNull($response->getPageInfo()->getPreviousPageUrl()); $this->assertTrue($response->getPageInfo()->hasNextPage()); /** @var RestResponse */ - $response = $client->get('products', [], $response->getPageInfo()->getNextPageQuery()); + $response = $client->get(path: 'products', query: $response->getPageInfo()->getNextPageQuery()); /** @var RestResponse */ - $response = $client->get('products', [], $response->getPageInfo()->getNextPageQuery()); + $response = $client->get(path: 'products', query: $response->getPageInfo()->getNextPageQuery()); $this->assertFalse($response->getPageInfo()->hasNextPage()); $this->assertNull($response->getPageInfo()->getNextPageUrl()); $this->assertTrue($response->getPageInfo()->hasPreviousPage()); /** @var RestResponse */ - $response = $client->get('products', [], $response->getPageInfo()->getPreviousPageQuery()); + $response = $client->get(path: 'products', query: $response->getPageInfo()->getPreviousPageQuery()); /** @var RestResponse */ - $response = $client->get('products', [], $response->getPageInfo()->getPreviousPageQuery()); + $response = $client->get(path: 'products', query: $response->getPageInfo()->getPreviousPageQuery()); $this->assertFalse($response->getPageInfo()->hasPreviousPage()); $this->assertNull($response->getPageInfo()->getPreviousPageUrl()); } diff --git a/tests/Clients/StorefrontTest.php b/tests/Clients/StorefrontTest.php index f67e4185..a78fa499 100644 --- a/tests/Clients/StorefrontTest.php +++ b/tests/Clients/StorefrontTest.php @@ -47,7 +47,7 @@ public function testCanMakeRequest() $client = new Storefront($this->domain, 'test_token'); - $response = $client->query($this->query); + $response = $client->query(data: $this->query); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals($this->successResponse, $response->getDecodedBody()); $this->assertEquals('request_id', $response->getRequestId()); @@ -74,7 +74,7 @@ public function testCanMakeRequestForPrivateApp() $client = new Storefront($this->domain); - $response = $client->query($this->query); + $response = $client->query(data: $this->query); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals($this->successResponse, $response->getDecodedBody()); $this->assertEquals('request_id', $response->getRequestId()); @@ -100,7 +100,7 @@ public function testCanUseTokenForPrivateAppRequest() $client = new Storefront($this->domain, 'test_token'); - $response = $client->query($this->query); + $response = $client->query(data: $this->query); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals($this->successResponse, $response->getDecodedBody()); $this->assertEquals('request_id', $response->getRequestId()); diff --git a/tests/ContextTest.php b/tests/ContextTest.php index 0cfaa897..3c465645 100644 --- a/tests/ContextTest.php +++ b/tests/ContextTest.php @@ -15,7 +15,13 @@ final class ContextTest extends BaseTestCase { public function testCanCreateContext() { - Context::initialize('ash', 'steffi', ['sleepy', 'kitty'], 'my-friends-cats', new MockSessionStorage()); + Context::initialize( + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: 'my-friends-cats', + sessionStorage: new MockSessionStorage(), + ); $this->assertEquals('ash', Context::$API_KEY); $this->assertEquals('steffi', Context::$API_SECRET_KEY); @@ -33,7 +39,13 @@ public function testCanCreateContext() // Context with different values has been set up in BaseTestCase public function testCanUpdateContext() { - Context::initialize('tuck', 'rocky', ['silly', 'doggo'], 'yay-for-doggos', new MockSessionStorage()); + Context::initialize( + apiKey: 'tuck', + apiSecretKey: 'rocky', + scopes: ['silly', 'doggo'], + hostName: 'yay-for-doggos', + sessionStorage: new MockSessionStorage(), + ); $this->assertEquals('tuck', Context::$API_KEY); $this->assertEquals('rocky', Context::$API_SECRET_KEY); @@ -47,7 +59,13 @@ public function testThrowsIfMissingArguments() $this->expectExceptionMessage( 'Cannot initialize Shopify API Library. Missing values for: apiKey, apiSecretKey, scopes, hostName' ); - Context::initialize('', '', [], '', new MockSessionStorage()); + Context::initialize( + apiKey: '', + apiSecretKey: '', + scopes: [], + hostName: '', + sessionStorage: new MockSessionStorage(), + ); } public function testThrowsIfUninitialized() @@ -66,14 +84,13 @@ public function testThrowsIfUninitialized() public function testThrowsIfPrivateApp() { Context::initialize( - 'ash', - 'steffi', - ['sleepy', 'kitty'], - 'my-friends-cats', - new MockSessionStorage(), - 'unstable', - true, - true, + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: 'my-friends-cats', + sessionStorage: new MockSessionStorage(), + apiVersion: 'unstable', + isPrivateApp: true, ); $this->expectException(\Shopify\Exception\PrivateAppException::class); $this->expectExceptionMessage('BOOOOOO'); @@ -122,7 +139,13 @@ public function testCanAddOverrideLogger() */ public function testCanSetHostScheme($host, $expectedScheme, $expectedHost) { - Context::initialize('ash', 'steffi', ['sleepy', 'kitty'], $host, new MockSessionStorage()); + Context::initialize( + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: $host, + sessionStorage: new MockSessionStorage(), + ); $this->assertEquals($expectedHost, Context::$HOST_NAME); $this->assertEquals($expectedScheme, Context::$HOST_SCHEME); @@ -142,7 +165,13 @@ public function canSetHostSchemeProvider() public function testFailsOnInvalidHost() { $this->expectException(\Shopify\Exception\InvalidArgumentException::class); - Context::initialize('ash', 'steffi', ['sleepy', 'kitty'], 'not-a-host-!@#$%^&*()', new MockSessionStorage()); + Context::initialize( + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: 'not-a-host-!@#$%^&*()', + sessionStorage: new MockSessionStorage(), + ); } public function testCanSetCustomShopDomains() @@ -150,18 +179,14 @@ public function testCanSetCustomShopDomains() $domains = ['*.special-domain-1.io', '*.special-domain-2.io']; Context::initialize( - 'ash', - 'steffi', - ['sleepy', 'kitty'], - 'my-friends-cats', - new MockSessionStorage(), - ApiVersion::LATEST, - true, - false, - null, - '', - null, - $domains + apiKey: 'ash', + apiSecretKey: 'steffi', + scopes: ['sleepy', 'kitty'], + hostName: 'my-friends-cats', + sessionStorage: new MockSessionStorage(), + apiVersion: ApiVersion::LATEST, + isPrivateApp: false, + customShopDomains: $domains, ); $this->assertEquals($domains, Context::$CUSTOM_SHOP_DOMAINS); diff --git a/tests/HttpRequestMatcher.php b/tests/HttpRequestMatcher.php index 1d17d632..9c84b307 100644 --- a/tests/HttpRequestMatcher.php +++ b/tests/HttpRequestMatcher.php @@ -53,7 +53,7 @@ public function __construct( $this->identicalBody = $identicalBody; } - protected function matches($other): bool + public function matches($other): bool { if (!($other instanceof RequestInterface)) { return false; diff --git a/tests/LogMock.php b/tests/LogMock.php index 297dc7a4..e11fad06 100644 --- a/tests/LogMock.php +++ b/tests/LogMock.php @@ -133,7 +133,7 @@ public function __call($method, $args) return call_user_func_array([$this, $genericMethod], $args); } } - throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + throw new \BadMethodCallException('Call to undefined method ' . $this::class . '::' . $method . '()'); } public function reset()