Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add category level attributes api support #3

Merged
merged 12 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php: ['8.0', '8.1', '8.2']
php: ['8.1', '8.2', '8.3']
composer: ['--prefer-lowest', '']
steps:
- name: Setup PHP
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ facade
│ └─ new - Obtain new session token
├─ category/ - Category endpoint
│ ├─ get - Get product listing category
│ └─ getAttributes - Get system-defined attributes based on category ID
│ ├─ getAttributes - Get system-defined attributes based on category ID
│ └─ getLevelAttribute - Get next-level attribute based on category, attribute and value ID (e.g. car_model values)
└─ product/ - Product endpoint
└─ getGroup - Get product group
```
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
}
],
"require": {
"php": "^8",
"php": "^8.1",
"ext-json": "*",
"ext-mbstring": "*",
"symfony/http-client": "^5.4 || ^6"
Expand Down
4 changes: 2 additions & 2 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Kyto\Alibaba;

use Kyto\Alibaba\Exception\AlibabaException;
use Kyto\Alibaba\Exception\ResponseException;
use Kyto\Alibaba\Util\Clock;
use Symfony\Contracts\HttpClient\HttpClientInterface;

Expand Down Expand Up @@ -96,7 +96,7 @@ private function throwOnError(array $data): void
$errorResponse = $data['error_response'] ?? null;

if ($errorResponse !== null) {
throw new AlibabaException(
throw new ResponseException(
$errorResponse['msg'],
(int) $errorResponse['code'],
$errorResponse['sub_msg'],
Expand Down
41 changes: 41 additions & 0 deletions src/Endpoint/CategoryEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace Kyto\Alibaba\Endpoint;

use Kyto\Alibaba\Client;
use Kyto\Alibaba\Exception\ResponseException;
use Kyto\Alibaba\Exception\UnexpectedResultException;
use Kyto\Alibaba\Factory\CategoryFactory;
use Kyto\Alibaba\Model\Category;
use Kyto\Alibaba\Model\CategoryAttribute;
use Kyto\Alibaba\Model\CategoryLevelAttribute;

class CategoryEndpoint
{
Expand All @@ -33,6 +36,7 @@ public function __construct(
* @link https://developer.alibaba.com/en/doc.htm?spm=a219a.7629140.0.0.188675fe5JPvEa#?docType=2&docId=50064
*
* @param ?string $id Provide `null` to fetch root categories
* @throws ResponseException
*/
public function get(?string $id = null): Category
{
Expand All @@ -51,6 +55,7 @@ public function get(?string $id = null): Category
* @link https://developer.alibaba.com/en/doc.htm?spm=a219a.7629140.0.0.188675fe5JPvEa#?docType=2&docId=25348
*
* @return CategoryAttribute[]
* @throws ResponseException
*/
public function getAttributes(string $categoryId): array
{
Expand All @@ -68,4 +73,40 @@ public function getAttributes(string $categoryId): array

return $result;
}

/**
* Get next-level attribute based on category, attribute and optionally level attribute value ID.
* @link https://developer.alibaba.com/en/doc.htm?spm=a2728.12183079.k2mwm9fd.1.4b3630901WuQWY#?docType=2&docId=48659
*
* @param ?string $valueId provide null to fetch root level
* @throws ResponseException|UnexpectedResultException
*/
public function getLevelAttribute(
string $categoryId,
string $attributeId,
?string $valueId = null
): CategoryLevelAttribute {
$attributeValueRequest = [
'cat_id' => $categoryId,
'attr_id' => $attributeId,
'value_id' => $valueId ?? '0'
];

$data = $this->client->request([
'method' => 'alibaba.icbu.category.level.attr.get',
'attribute_value_request' => json_encode($attributeValueRequest)
Dominik-Czulak marked this conversation as resolved.
Show resolved Hide resolved
]);

$errorMessage = sprintf(
'Result list for category id: "%s", attribute id: "%s", value id: "%s" is empty.',
$categoryId,
$attributeId,
$valueId
);

$attribute = $data['alibaba_icbu_category_level_attr_get_response']['result_list']
?? throw new UnexpectedResultException($errorMessage);

return $this->categoryFactory->createLevelAttribute($attribute);
}
}
2 changes: 2 additions & 0 deletions src/Endpoint/ProductEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Kyto\Alibaba\Endpoint;

use Kyto\Alibaba\Client;
use Kyto\Alibaba\Exception\ResponseException;
use Kyto\Alibaba\Factory\ProductFactory;
use Kyto\Alibaba\Model\ProductGroup;
use Kyto\Alibaba\Model\Token;
Expand Down Expand Up @@ -33,6 +34,7 @@ public function __construct(
* @link https://developer.alibaba.com/en/doc.htm?spm=a219a.7629140.0.0.188675fe5JPvEa#?docType=2&docId=25299
*
* @param ?string $id Provide `null` to fetch root groups
* @throws ResponseException
*/
public function getGroup(Token $token, ?string $id = null): ProductGroup
{
Expand Down
3 changes: 3 additions & 0 deletions src/Endpoint/TokenEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Kyto\Alibaba\Endpoint;

use Kyto\Alibaba\Client;
use Kyto\Alibaba\Exception\ResponseException;
use Kyto\Alibaba\Factory\TokenFactory;
use Kyto\Alibaba\Model\Token;

Expand All @@ -31,6 +32,8 @@ public function __construct(
* To obtain authorization code see corresponding facade method.
* @link https://open.taobao.com/api.htm?spm=a219a.7386653.0.0.41449b714zR8KI&docId=25388&docType=2&source=search
* @see \Kyto\Alibaba\Facade::getAuthorizationUrl
*
* @throws ResponseException|\JsonException
*/
public function new(string $authorizationCode): Token
{
Expand Down
12 changes: 12 additions & 0 deletions src/Enum/InputType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Kyto\Alibaba\Enum;

enum InputType: string
{
case INPUT = 'input';
case MULTI_SELECT = 'multi_select';
case SINGLE_SELECT = 'single_select';
}
15 changes: 15 additions & 0 deletions src/Enum/ShowType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Kyto\Alibaba\Enum;

enum ShowType: string
{
case CHECK_BOX = 'check_box'; // multi_select
case GROUP_TABLE = 'group_table'; // single_select
case INPUT = 'input'; // input (string)
case INTERVAL = 'interval'; // input (number)
case LIST_BOX = 'list_box'; // single_select
case MODEL_NUMBERS = 'model_numbers'; // input (string)
}
11 changes: 11 additions & 0 deletions src/Enum/ValueType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Kyto\Alibaba\Enum;

enum ValueType: string
{
case NUMBER = 'number';
case STRING = 'string';
}
25 changes: 1 addition & 24 deletions src/Exception/AlibabaException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,6 @@

namespace Kyto\Alibaba\Exception;

class AlibabaException extends \RuntimeException
abstract class AlibabaException extends \RuntimeException
Dominik-Czulak marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* @internal
*/
public function __construct(
string $message,
int $code,
private string $subMessage,
private string $subCode,
?\Throwable $previous = null
) {
$message = sprintf('%s. Sub-code: "%s". Sub-message: "%s".', $message, $this->subCode, $this->subMessage);
parent::__construct($message, $code, $previous);
}

public function getSubMessage(): string
{
return $this->subMessage;
}

public function getSubCode(): string
{
return $this->subCode;
}
}
32 changes: 32 additions & 0 deletions src/Exception/ResponseException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Kyto\Alibaba\Exception;

class ResponseException extends AlibabaException
{
/**
* @internal
*/
public function __construct(
string $message,
int $code,
private string $subMessage,
private string $subCode,
?\Throwable $previous = null
) {
$message = sprintf('%s. Sub-code: "%s". Sub-message: "%s".', $message, $this->subCode, $this->subMessage);
parent::__construct($message, $code, $previous);
}

public function getSubMessage(): string
{
return $this->subMessage;
}

public function getSubCode(): string
{
return $this->subCode;
}
}
19 changes: 19 additions & 0 deletions src/Exception/UnexpectedResultException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Kyto\Alibaba\Exception;

class UnexpectedResultException extends AlibabaException
{
/**
* @internal
*/
public function __construct(
string $message,
int $code = 0,
?\Throwable $previous = null
) {
parent::__construct($message, $code, $previous);
}
}
49 changes: 43 additions & 6 deletions src/Factory/CategoryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

namespace Kyto\Alibaba\Factory;

use Kyto\Alibaba\Enum\InputType;
use Kyto\Alibaba\Enum\ShowType;
use Kyto\Alibaba\Enum\ValueType;
use Kyto\Alibaba\Model\CategoryLevelAttribute;
use Kyto\Alibaba\Model\CategoryLevelAttributeValue;
use Kyto\Alibaba\Util\Formatter;
use Kyto\Alibaba\Model\Category;
use Kyto\Alibaba\Model\CategoryAttribute;
Expand All @@ -15,7 +20,7 @@
class CategoryFactory
{
/**
* @param mixed[] $data
* @param array<string, mixed> $data
*/
public function createCategory(array $data): Category
{
Expand All @@ -34,7 +39,7 @@ public function createCategory(array $data): Category
}

/**
* @param mixed[] $data
* @param array<string, mixed> $data
*/
public function createAttribute(array $data): CategoryAttribute
{
Expand All @@ -44,9 +49,9 @@ public function createAttribute(array $data): CategoryAttribute
$model->name = (string) $data['en_name'];
$model->isRequired = (bool) $data['required'];

$model->inputType = (string) $data['input_type'];
$model->showType = (string) $data['show_type'];
$model->valueType = (string) $data['value_type'];
$model->inputType = InputType::from($data['input_type']);
$model->showType = ShowType::from($data['show_type']);
$model->valueType = ValueType::from($data['value_type']);

$model->isSku = (bool) $data['sku_attribute'];
$model->hasCustomizeImage = (bool) $data['customize_image'];
Expand All @@ -64,7 +69,7 @@ public function createAttribute(array $data): CategoryAttribute
}

/**
* @param mixed[] $data
* @param array<string, mixed> $data
*/
public function createAttributeValue(array $data): CategoryAttributeValue
{
Expand All @@ -77,4 +82,36 @@ public function createAttributeValue(array $data): CategoryAttributeValue

return $model;
}

/**
* @param array<string, mixed> $data
*/
public function createLevelAttribute(array $data): CategoryLevelAttribute
Dominik-Czulak marked this conversation as resolved.
Show resolved Hide resolved
{
$model = new CategoryLevelAttribute();

$model->id = (string) $data['property_id'];
$model->name = (string) $data['property_en_name'];

$model->values = [];
$decodedValues = json_decode($data['values'], true);
Dominik-Czulak marked this conversation as resolved.
Show resolved Hide resolved
foreach ($decodedValues as $value) {
$model->values[] = $this->createLevelAttributeValue($value);
}

return $model;
}

/**
* @param array<string, mixed> $data
*/
public function createLevelAttributeValue(array $data): CategoryLevelAttributeValue
Dominik-Czulak marked this conversation as resolved.
Show resolved Hide resolved
{
$model = new CategoryLevelAttributeValue();
$model->name = (string) $data['name'];
$model->id = (string) $data['id'];
$model->isLeaf = isset($data['leaf']);

return $model;
}
}
11 changes: 7 additions & 4 deletions src/Model/CategoryAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@

namespace Kyto\Alibaba\Model;

use Kyto\Alibaba\Enum\InputType;
use Kyto\Alibaba\Enum\ShowType;
use Kyto\Alibaba\Enum\ValueType;

class CategoryAttribute
{
public string $id;
public string $name;
public bool $isRequired;

// TODO: change to enums once all values would be known
public string $inputType; // Known values: single_select, multi_select, input
public string $showType; // Known values: list_box (single_select), check_box (multi_select), input (input)
public string $valueType; // Known values: string, number
public InputType $inputType;
public ShowType $showType;
public ValueType $valueType;

public bool $isSku;
public bool $hasCustomizeImage;
Expand Down
Loading
Loading