Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace App\Command;

use Ibexa\Contracts\Core\Repository\ContentTypeService;
use Ibexa\Contracts\Core\Repository\PermissionResolver;
use Ibexa\Contracts\Core\Repository\UserService;
use Ibexa\Contracts\ProductCatalog\AttributeDefinitionServiceInterface;
use Ibexa\Contracts\ProductCatalog\Local\LocalProductTypeServiceInterface;
use Ibexa\Contracts\ProductCatalog\Local\Values\ProductType\AssignAttributeDefinitionStruct;
use Ibexa\Contracts\ProductCatalog\ProductTypeServiceInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
Expand All @@ -18,11 +22,26 @@ final class ProductTypeCommand extends Command

private ProductTypeServiceInterface $productTypeService;

public function __construct(UserService $userService, PermissionResolver $permissionResolver, ProductTypeServiceInterface $productTypeService)
{
private LocalProductTypeServiceInterface $localProductTypeService;

private ContentTypeService $contentTypeService;

private AttributeDefinitionServiceInterface $attributeDefinitionService;

public function __construct(
UserService $userService,
PermissionResolver $permissionResolver,
ProductTypeServiceInterface $productTypeService,
LocalProductTypeServiceInterface $localProductTypeService,
ContentTypeService $contentTypeService,
AttributeDefinitionServiceInterface $attributeDefinitionService
) {
$this->userService = $userService;
$this->permissionResolver = $permissionResolver;
$this->productTypeService = $productTypeService;
$this->localProductTypeService = $localProductTypeService;
$this->contentTypeService = $contentTypeService;
$this->attributeDefinitionService = $attributeDefinitionService;
parent::__construct('doc:product_type');
}

Expand All @@ -41,6 +60,40 @@ protected function execute(InputInterface $input, OutputInterface $output): int

$productTypeIdentifier = $input->getArgument('productTypeIdentifier');

$productTypeCreateStruct = $this->localProductTypeService->newProductTypeCreateStruct(
'digital_product',
'eng-GB'
);

$productTypeCreateStruct->setNames([
'eng-GB' => 'Digital Product',
'pol-PL' => 'Produkt Cyfrowy',
]);

$productTypeCreateStruct->setVirtual(true);

$contentTypeCreateStruct = $productTypeCreateStruct->getContentTypeCreateStruct();

$marketingDescriptionFieldDefinition = $this->contentTypeService->newFieldDefinitionCreateStruct(
'marketing_description',
'ezstring'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: on upmerge, this should be ibexa_string

);
$marketingDescriptionFieldDefinition->names = ['eng-GB' => 'Marketing Description'];
$marketingDescriptionFieldDefinition->position = 100;
$contentTypeCreateStruct->addFieldDefinition($marketingDescriptionFieldDefinition);

$sizeAttribute = $this->attributeDefinitionService->getAttributeDefinition('size');

$attributeAssignment = new AssignAttributeDefinitionStruct(
$sizeAttribute,
false,
false
);

$productTypeCreateStruct->setAssignedAttributesDefinitions([$attributeAssignment]);

$newProductType = $this->localProductTypeService->createProductType($productTypeCreateStruct);

$productType = $this->productTypeService->getProductType($productTypeIdentifier);

$output->writeln($productType->getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"_media-type": "application/vnd.ibexa.api.ProductType+json",
"identifier": "test_pt321",
"name": "New Product Type",
"is_virtual": false,
"AttributeAssignmentList": [
{
"_media-type": "application/vnd.ibexa.api.AttributeAssignment+json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"is_required": false,
"is_discriminator": true
}
]
],
"is_virtual": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"_media-type": "application/vnd.ibexa.api.ProductType+json",
"identifier": "climbing_shoe",
"name": "New Product Type",
"is_virtual": false,
"AttributeAssignmentList": [
{
"_media-type": "application/vnd.ibexa.api.AttributeAssignment+json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"_media-type": "application/vnd.ibexa.api.ProductType+json",
"identifier": "d_rope",
"name": "Dynamic ropes",
"is_virtual": false,
"AttributeAssignmentList": []
}
}
4 changes: 4 additions & 0 deletions docs/api/rest_api/rest_api_reference/input/ibexa-types.raml
Original file line number Diff line number Diff line change
Expand Up @@ -4526,6 +4526,10 @@ ProductTypeCreate:
assigned_attributes:
type: array
items: ProductTypeAssignedAttribute
is_virtual:
type: boolean
required: false
description: 'Determines whether the product type is virtual (digital products) or physical. Defaults to false (physical).'

ProductTypeUpdateWrapper:
description: 'JSON object with only a ProductTypeUpdate property.'
Expand Down
10 changes: 10 additions & 0 deletions docs/pim/pim_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@

![Product categories](img/product_categories.png)

### Virtual and physical products

Product types in [[= product_name =]] can be either virtual or physical:

- **Physical products** are tangible items that require shipping (for example: books, clothing, electronics).

Check failure on line 86 in docs/pim/pim_guide.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/pim_guide.md#L86

[Ibexa.Lists] Do not put fullstops at the end of bullets
Raw output
{"message": "[Ibexa.Lists] Do not put fullstops at the end of bullets", "location": {"path": "docs/pim/pim_guide.md", "range": {"start": {"line": 86, "column": 109}}}, "severity": "ERROR"}
- **Virtual products** are digital items that don't require physical delivery (for example: software licenses, e-books, online courses, digital downloads).

Check failure on line 87 in docs/pim/pim_guide.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/pim_guide.md#L87

[Ibexa.Lists] Do not put fullstops at the end of bullets
Raw output
{"message": "[Ibexa.Lists] Do not put fullstops at the end of bullets", "location": {"path": "docs/pim/pim_guide.md", "range": {"start": {"line": 87, "column": 155}}}, "severity": "ERROR"}

This product type property affects the checkout process.
Virtual products skip the [shipping step](shipping_management.md) during checkout.

### Currencies

Currencies are used when calculating product price. In the system you can find a list of available currencies, but you can also create custom ones by providing its code.
Expand Down
61 changes: 59 additions & 2 deletions docs/pim/product_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,73 @@

To work with product types, use [`ProductTypeServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductTypeServiceInterface.html).

### Creating product types

To create a product type, use [`LocalProductTypeServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalProductTypeServiceInterface.html).

Check failure on line 110 in docs/pim/product_api.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/product_api.md#L110

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/pim/product_api.md", "range": {"start": {"line": 110, "column": 107}}}, "severity": "ERROR"}

First, create a product type struct with `LocalProductTypeServiceInterface::newProductTypeCreateStruct()`, providing the identifier and main language code:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 62, 66) =]]
```

You can set names in multiple languages by using `setNames()`:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 67, 71) =]]
```

To create a virtual product type (for digital products that don't require shipping), use `setVirtual()`:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 72, 73) =]]
```

#### Adding field definitions

To add custom field definitions to the product type, use `getContentTypeCreateStruct()` to access the underlying content type struct.
For more information about working with content types, see [Adding content types](../content_management/content_api/managing_content.md#adding-content-types).

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 76, 83) =]]
```

#### Assigning attributes

To assign product attributes to the product type, use `setAssignedAttributesDefinitions()` with an array of [`AssignAttributeDefinitionStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-Values-ProductType-AssignAttributeDefinitionStruct.html) objects.

Check failure on line 141 in docs/pim/product_api.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/product_api.md#L141

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/pim/product_api.md", "range": {"start": {"line": 141, "column": 184}}}, "severity": "ERROR"}

First, retrieve the attribute definition using [`AttributeDefinitionServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-AttributeDefinitionServiceInterface.html):

Check failure on line 143 in docs/pim/product_api.md

View workflow job for this annotation

GitHub Actions / vale

[vale] docs/pim/product_api.md#L143

[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'
Raw output
{"message": "[Ibexa.VariablesGlobal] Use global variable '[[= product_name_base =]]' instead of 'Ibexa'", "location": {"path": "docs/pim/product_api.md", "range": {"start": {"line": 143, "column": 127}}}, "severity": "ERROR"}

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 84, 85) =]]
```

Then create the assignment struct with the attribute definition, and set whether it's required and whether it's a discriminator (used for product variants):

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 86, 93) =]]
```

For more information about working with attributes through PHP API, see [Attributes](#attributes).

Finally, create the product type with `LocalProductTypeServiceInterface::createProductType()`:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 94, 95) =]]
```

### Getting product types

Get a product type object by using `ProductTypeServiceInterface::getProductType()`:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 43, 44) =]]
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 96, 96) =]]
```

You can also get a list of product types with `ProductTypeServiceInterface::findProductTypes()`:

``` php
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 47, 52) =]]
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 100, 105) =]]
```

## Product availability
Expand Down