Skip to content
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
61 changes: 39 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ $response = $client->getProducts(lastUpdateFrom: $since);

// Filter only edited products
$response = $client->getProducts(isEdited: true);

// Include optional content (marketplace HTML, raw widget JSON)
use Pobo\Sdk\Enum\IncludeContent;

$response = $client->getProducts(include: [IncludeContent::MARKETPLACE, IncludeContent::NESTED]);
```

### Export Categories
Expand Down Expand Up @@ -288,41 +293,53 @@ foreach ($client->iterateBlogs() as $blog) {
}
```

## Content (HTML/Marketplace)
## Content (HTML/Marketplace/Nested)

Products, categories, and blogs include a `content` field with generated HTML content for web and marketplace:
By default, only `content.html` is returned. Use the `include` parameter to request additional content:

| Value | Description |
|---------------|----------------------------------------------|
| `marketplace` | HTML content for marketplace (no custom CSS) |
| `nested` | Raw widget JSON from widget tables |

```php
use Pobo\Sdk\Enum\IncludeContent;
use Pobo\Sdk\Enum\Language;

foreach ($client->iterateProducts() as $product) {
// Include marketplace and nested content
foreach ($client->iterateProducts(include: [IncludeContent::MARKETPLACE, IncludeContent::NESTED]) as $product) {
if ($product->content !== null) {
// Get HTML content for web
// Get HTML content for web (always included)
$htmlCs = $product->content->getHtml(Language::CS);
$htmlSk = $product->content->getHtml(Language::SK);
$htmlEn = $product->content->getHtml(Language::EN);

// Get content for marketplace
// Get content for marketplace (requires include: ['marketplace'])
$marketplaceCs = $product->content->getMarketplace(Language::CS);
$marketplaceSk = $product->content->getMarketplace(Language::SK);

// Get raw widget JSON (requires include: ['nested'])
$nested = $product->content->getNested();

// Get default content
$htmlDefault = $product->content->getHtmlDefault();
$marketplaceDefault = $product->content->getMarketplaceDefault();
}
}

// Same for categories
foreach ($client->iterateCategories() as $category) {
foreach ($client->iterateCategories(include: [IncludeContent::NESTED]) as $category) {
if ($category->content !== null) {
echo $category->content->getHtml(Language::CS);
$nested = $category->content->getNested();
}
}

// Same for blogs
foreach ($client->iterateBlogs() as $blog) {
foreach ($client->iterateBlogs(include: [IncludeContent::MARKETPLACE]) as $blog) {
if ($blog->content !== null) {
echo $blog->content->getHtml(Language::CS);
echo $blog->content->getMarketplace(Language::CS);
}
}
```
Expand Down Expand Up @@ -426,21 +443,21 @@ $name->toArray(); // ['default' => '...', 'cs' => '...', ...]

## API Methods

| Method | Description |
|----------------------------------------------------------------------------------------|----------------------------------|
| `importProducts(array $products)` | Bulk import products (max 100) |
| `importCategories(array $categories)` | Bulk import categories (max 100) |
| `importParameters(array $parameters)` | Bulk import parameters (max 100) |
| `importBlogs(array $blogs)` | Bulk import blogs (max 100) |
| `deleteProducts(array $ids)` | Bulk delete products (max 100) |
| `deleteCategories(array $ids)` | Bulk delete categories (max 100) |
| `deleteBlogs(array $ids)` | Bulk delete blogs (max 100) |
| `getProducts(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited)` | Get products page |
| `getCategories(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited)` | Get categories page |
| `getBlogs(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited)` | Get blogs page |
| `iterateProducts(?DateTime $lastUpdateFrom, ?bool $isEdited)` | Iterate all products |
| `iterateCategories(?DateTime $lastUpdateFrom, ?bool $isEdited)` | Iterate all categories |
| `iterateBlogs(?DateTime $lastUpdateFrom, ?bool $isEdited)` | Iterate all blogs |
| Method | Description |
|---------------------------------------------------------------------------------------------------------|----------------------------------|
| `importProducts(array $products)` | Bulk import products (max 100) |
| `importCategories(array $categories)` | Bulk import categories (max 100) |
| `importParameters(array $parameters)` | Bulk import parameters (max 100) |
| `importBlogs(array $blogs)` | Bulk import blogs (max 100) |
| `deleteProducts(array $ids)` | Bulk delete products (max 100) |
| `deleteCategories(array $ids)` | Bulk delete categories (max 100) |
| `deleteBlogs(array $ids)` | Bulk delete blogs (max 100) |
| `getProducts(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Get products page |
| `getCategories(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Get categories page |
| `getBlogs(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Get blogs page |
| `iterateProducts(?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Iterate all products |
| `iterateCategories(?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Iterate all categories |
| `iterateBlogs(?DateTime $lastUpdateFrom, ?bool $isEdited, ?array $include)` | Iterate all blogs |

## Limits

Expand Down
21 changes: 19 additions & 2 deletions src/DTO/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ final class Content
/**
* @param array<string, string> $html
* @param array<string, string> $marketplace
* @param array<int, array<mixed>> $nested
*/
public function __construct(
public readonly array $html = [],
public readonly array $marketplace = [],
public readonly array $nested = [],
) {
}

Expand All @@ -39,14 +41,28 @@ public function getMarketplaceDefault(): ?string
}

/**
* @return array<string, array<string, string>>
* @return array<int, array<mixed>>
*/
public function getNested(): array
{
return $this->nested;
}

/**
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
$result = [
'html' => $this->html,
'marketplace' => $this->marketplace,
];

if ($this->nested !== []) {
$result['nested'] = $this->nested;
}

return $result;
}

/**
Expand All @@ -57,6 +73,7 @@ public static function fromArray(array $data): self
return new self(
html: $data['html'] ?? [],
marketplace: $data['marketplace'] ?? [],
nested: $data['nested'] ?? [],
);
}
}
24 changes: 24 additions & 0 deletions src/Enum/IncludeContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Pobo\Sdk\Enum;

enum IncludeContent: string
{
case MARKETPLACE = 'marketplace';
case NESTED = 'nested';

/**
* @return array<string>
*/
public static function values(): array
{
return array_column(self::cases(), 'value');
}

public static function isValid(string $value): bool
{
return in_array($value, self::values(), true);
}
}
37 changes: 31 additions & 6 deletions src/PoboClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Pobo\Sdk\DTO\PaginatedResponse;
use Pobo\Sdk\DTO\Parameter;
use Pobo\Sdk\DTO\Product;
use Pobo\Sdk\Enum\IncludeContent;
use Pobo\Sdk\Exception\ApiException;
use Pobo\Sdk\Exception\ValidationException;

Expand Down Expand Up @@ -100,43 +101,49 @@ public function importBlogs(array $blogs): ImportResult
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @throws ApiException
*/
public function getProducts(
?int $page = null,
?int $perPage = null,
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): PaginatedResponse {
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited);
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited, $include);
$response = $this->request('GET', '/api/v2/rest/products' . $query);
return PaginatedResponse::fromArray($response, Product::class);
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @throws ApiException
*/
public function getCategories(
?int $page = null,
?int $perPage = null,
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): PaginatedResponse {
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited);
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited, $include);
$response = $this->request('GET', '/api/v2/rest/categories' . $query);
return PaginatedResponse::fromArray($response, Category::class);
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @throws ApiException
*/
public function getBlogs(
?int $page = null,
?int $perPage = null,
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): PaginatedResponse {
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited);
$query = $this->buildQueryParams($page, $perPage, $lastUpdateFrom, $isEdited, $include);
$response = $this->request('GET', '/api/v2/rest/blogs' . $query);
return PaginatedResponse::fromArray($response, Blog::class);
}
Expand Down Expand Up @@ -187,17 +194,19 @@ public function deleteBlogs(array $ids): DeleteResult
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @return \Generator<Product>
* @throws ApiException
*/
public function iterateProducts(
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): \Generator {
$page = 1;

do {
$response = $this->getProducts($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited);
$response = $this->getProducts($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited, $include);

foreach ($response->data as $product) {
yield $product;
Expand All @@ -208,17 +217,19 @@ public function iterateProducts(
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @return \Generator<Category>
* @throws ApiException
*/
public function iterateCategories(
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): \Generator {
$page = 1;

do {
$response = $this->getCategories($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited);
$response = $this->getCategories($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited, $include);

foreach ($response->data as $category) {
yield $category;
Expand All @@ -229,17 +240,19 @@ public function iterateCategories(
}

/**
* @param array<IncludeContent|string>|null $include Optional content to include: IncludeContent::MARKETPLACE, IncludeContent::NESTED
* @return \Generator<Blog>
* @throws ApiException
*/
public function iterateBlogs(
?\DateTimeInterface $lastUpdateFrom = null,
?bool $isEdited = null,
?array $include = null,
): \Generator {
$page = 1;

do {
$response = $this->getBlogs($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited);
$response = $this->getBlogs($page, self::MAX_BULK_ITEMS, $lastUpdateFrom, $isEdited, $include);

foreach ($response->data as $blog) {
yield $blog;
Expand All @@ -264,11 +277,15 @@ private function validateBulkSize(array $items): void
}
}

/**
* @param array<IncludeContent|string>|null $include
*/
private function buildQueryParams(
?int $page,
?int $perPage,
?\DateTimeInterface $lastUpdateFrom,
?bool $isEdited,
?array $include = null,
): string {
$params = [];

Expand All @@ -288,6 +305,14 @@ private function buildQueryParams(
$params['is_edited'] = $isEdited === true ? 'true' : 'false';
}

if ($include !== null && $include !== []) {
$values = array_map(
fn(IncludeContent|string $item) => $item instanceof IncludeContent ? $item->value : $item,
$include,
);
$params['include'] = implode(',', $values);
}

return $params === [] ? '' : sprintf('?%s', http_build_query($params));
}

Expand Down
Loading