Skip to content

Commit

Permalink
Merge pull request #37 from aligent/feature/implemement-custom-templa…
Browse files Browse the repository at this point in the history
…tes-api

Implemement custom templates api
  • Loading branch information
jswift authored Mar 19, 2021
2 parents eb2c359 + 90c5256 commit 6ee01e6
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 25 deletions.
3 changes: 2 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
### New Features

Until BigCommerce decide to be consistent and include a _Get Customer_ endpoint, add `CustomersApi::getById(int $id)`.
Implement the new (Custom Template Associations)[https://developer.bigcommerce.com/api-reference/store-management/custom-template-associations]
API.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace BigCommerce\ApiV3\Api\CustomTemplateAssociations;

use BigCommerce\ApiV3\Api\Generic\BatchUpdateResource;
use BigCommerce\ApiV3\Api\Generic\GetAllResources;
use BigCommerce\ApiV3\Api\Generic\V3ApiBase;
use BigCommerce\ApiV3\ResourceModels\CustomTemplateAssociation\CustomTemplateAssociation;
use BigCommerce\ApiV3\ResponseModels\CustomTemplateAssociation\CustomTemplateAssociationsResponse;
use GuzzleHttp\RequestOptions;

class CustomTemplateAssociationsApi extends V3ApiBase
{
use GetAllResources;
use BatchUpdateResource;

private const TEMPLATES_ENDPOINT = '/storefront/custom-template-associations';

public const FILTER_CHANNEL_ID = 'channel_id';
public const FILTER_ENTITY_ID_IN = 'entity_id:in';
public const FILTER_TYPE = 'type';
public const FILTER_IS_VALID = 'is_valid';

public const DELETE_QUERY_ID_IN = 'id:in';
public const DELETE_QUERY_ENTITY_ID_IN = 'entity_id:in';
public const DELETE_QUERY_CHANNEL_ID = 'channel_id';
public const DELETE_QUERY_TYPE = 'type';

protected function maxBatchSize(): int
{
return 100;
}

public function getAll(array $filters = [], int $page = 1, int $limit = 250): CustomTemplateAssociationsResponse
{
return new CustomTemplateAssociationsResponse($this->getAllResources($filters, $page, $limit));
}

/**
* @param CustomTemplateAssociation[] $templateAssociations
* @return CustomTemplateAssociationsResponse
*/
public function batchUpdate(array $templateAssociations): CustomTemplateAssociationsResponse
{
return CustomTemplateAssociationsResponse::buildFromMultipleResponses(
$this->batchUpdateResource($templateAssociations)
);
}

public function multipleResourcesEndpoint(): string
{
return self::TEMPLATES_ENDPOINT;
}

public function multipleResourceUrl(): string
{
return $this->multipleResourcesEndpoint();
}

public function delete(array $query): void
{
$this->getClient()->getRestClient()->delete(
$this->multipleResourceUrl(),
[
RequestOptions::QUERY => $query
]
);
}

public function deleteByIds(array $ids): void
{
$this->delete([
self::DELETE_QUERY_ID_IN => $ids
]);
}

public function deleteByChannelId(int $channelId): void
{
$this->delete([
self::DELETE_QUERY_CHANNEL_ID => $channelId
]);
}

public function deleteByEntityIds(string $type, array $ids): void
{
$this->delete([
self::DELETE_QUERY_ENTITY_ID_IN => $ids,
self::DELETE_QUERY_TYPE => $type,
]);
}
}
40 changes: 40 additions & 0 deletions src/BigCommerce/Api/Generic/BatchUpdateResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace BigCommerce\ApiV3\Api\Generic;

use BigCommerce\ApiV3\Client;
use BigCommerce\ApiV3\ResponseModels\PaginatedResponse;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\ResponseInterface;

trait BatchUpdateResource
{
abstract public function batchUpdate(array $resources): PaginatedResponse;
abstract public function multipleResourcesEndpoint(): string;
abstract public function getClient(): Client;

protected function maxBatchSize(): int
{
return 10;
}

/**
* @param array $resources
* @return ResponseInterface[]
*/
protected function batchUpdateResource(array $resources): array
{
$chunks = array_chunk($resources, $this->maxBatchSize());
$responses = [];
foreach ($chunks as $chunk) {
$responses[] = $this->getClient()->getRestClient()->put(
$this->multipleResourcesEndpoint(),
[
RequestOptions::JSON => $chunk,
]
);
}

return $responses;
}
}
25 changes: 1 addition & 24 deletions src/BigCommerce/Api/Generic/ResourceWithBatchUpdateApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,5 @@

abstract class ResourceWithBatchUpdateApi extends ResourceApi
{
protected const MAX_BATCH_SIZE = 10;

abstract public function batchUpdate(array $resources): PaginatedResponse;

/**
* @param array $resources
* @return ResponseInterface[]
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function batchUpdateResource(array $resources): array
{
$chunks = array_chunk($resources, self::MAX_BATCH_SIZE);
$responses = [];
foreach ($chunks as $chunk) {
$responses[] = $this->getClient()->getRestClient()->put(
$this->multipleResourcesEndpoint(),
[
RequestOptions::JSON => $chunk,
]
);
}

return $responses;
}
use BatchUpdateResource;
}
6 changes: 6 additions & 0 deletions src/BigCommerce/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use BigCommerce\ApiV3\Api\Scripts\ScriptsApi;
use BigCommerce\ApiV3\Api\Themes\ThemesApi;
use BigCommerce\ApiV3\Api\Widgets\WidgetsApi;
use BigCommerce\ApiV3\Api\CustomTemplateAssociations\CustomTemplateAssociationsApi;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;

Expand Down Expand Up @@ -159,4 +160,9 @@ public function content(): WidgetsApi
{
return $this->widgets();
}

public function customTemplateAssociations(): CustomTemplateAssociationsApi
{
return new CustomTemplateAssociationsApi($this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace BigCommerce\ApiV3\ResourceModels\CustomTemplateAssociation;

use BigCommerce\ApiV3\ResourceModels\ResourceModel;

class CustomTemplateAssociation extends ResourceModel
{
public const TYPE_PRODUCT = 'product';
public const TYPE_CATEGORY = 'category';
public const TYPE_BRAND = 'brand';
public const TYPE_PAGE = 'page';

public int $id;
public int $channel_id;
public string $entity_type;
public int $entity_id;
public string $file_name;
public ?bool $is_valid;
public string $date_created;
public string $date_modified;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace BigCommerce\ApiV3\ResponseModels\CustomTemplateAssociation;

use BigCommerce\ApiV3\ResponseModels\PaginatedBatchableResponse;
use BigCommerce\ApiV3\ResourceModels\CustomTemplateAssociation\CustomTemplateAssociation;

class CustomTemplateAssociationsResponse extends PaginatedBatchableResponse
{
/**
* @return CustomTemplateAssociation[]
*/
public function getCustomTemplateAssociations(): array
{
return $this->getData();
}

protected function resourceClass(): string
{
return CustomTemplateAssociation::class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public function getSubscribers(): array
{
return $this->getData();
}

protected function resourceClass(): string
{
return Subscriber::class;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace BigCommerce\Tests\Api\CustomTemplateAssociation;

use BigCommerce\ApiV3\Api\CustomTemplateAssociations\CustomTemplateAssociationsApi;
use BigCommerce\ApiV3\ResourceModels\CustomTemplateAssociation\CustomTemplateAssociation;
use BigCommerce\Tests\BigCommerceApiTest;

class CustomTemplateAssociationsApiTest extends BigCommerceApiTest
{
public function testCanGetAssociations()
{
$this->setReturnData('templates__get_all.json');

$response = $this->getApi()->customTemplateAssociations()->getAll();
$this->assertEquals(5, $response->getPagination()->count);
$this->assertEquals('custom-product-1.html', $response->getCustomTemplateAssociations()[0]->file_name);
}

public function testCanDeleteAssociation()
{
$this->setReturnData(self::EMPTY_RESPONSE, 204);

$customTemplateAssocApi = $this->getApi()->customTemplateAssociations();
$customTemplateAssocApi->deleteByChannelId(1);
$this->setReturnData(self::EMPTY_RESPONSE, 204);
$customTemplateAssocApi->deleteByIds([1, 2, 3]);
$this->setReturnData(self::EMPTY_RESPONSE, 204);
$customTemplateAssocApi->deleteByEntityIds(CustomTemplateAssociation::TYPE_CATEGORY, [4, 5, 6]);
$this->assertTrue(true);
}

public function testCanUpsertAssociation()
{
$this->setReturnData('templates__get_all.json');
$templateAssociationOne = new CustomTemplateAssociation((object)[
"id" => 1,
"channel_id" => 1,
"entity_type" => "product",
"entity_id" => 123,
"file_name" => "custom-product-1.html",
]);

$templateAssociationTwo = new CustomTemplateAssociation((object)[
"id" => 2,
"channel_id" => 12345,
"entity_type" => "page",
"entity_id" => 123,
"file_name" => "custom-page.html",
]);

$this->getApi()->customTemplateAssociations()->batchUpdate([
$templateAssociationOne, $templateAssociationTwo
]);

$this->assertTrue(true);
}
}
31 changes: 31 additions & 0 deletions tests/BigCommerce/responses/templates__get_all.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"data": [
{
"id": 1,
"channel_id": 1,
"entity_type": "product",
"entity_id": 123,
"file_name": "custom-product-1.html"
},
{
"id": 2,
"channel_id": 12345,
"entity_type": "page",
"entity_id": 123,
"file_name": "custom-page.html"
}
],
"meta": {
"pagination": {
"total": 246,
"count": 5,
"per_page": 5,
"current_page": 1,
"total_pages": 50,
"links": {
"next": "?limit=5&page=2",
"current": "?limit=5&page=1"
}
}
}
}

0 comments on commit 6ee01e6

Please sign in to comment.