Skip to content

Commit 20dec31

Browse files
mnoconadriendupuisdabrt
authored
Described virtual products and added an example creating product type with PHP API (#3024)
* Described virtual products and added an example creating product type with PHP API * Apply suggestions from code review Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> * Fixed invalid include * Apply suggestions from code review Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com> * Added link to user doc --------- Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com>
1 parent c774f5b commit 20dec31

8 files changed

Lines changed: 138 additions & 7 deletions

File tree

code_samples/api/product_catalog/src/Command/ProductTypeCommand.php

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
namespace App\Command;
44

5+
use Ibexa\Contracts\Core\Repository\ContentTypeService;
56
use Ibexa\Contracts\Core\Repository\PermissionResolver;
67
use Ibexa\Contracts\Core\Repository\UserService;
8+
use Ibexa\Contracts\ProductCatalog\AttributeDefinitionServiceInterface;
9+
use Ibexa\Contracts\ProductCatalog\Local\LocalProductTypeServiceInterface;
10+
use Ibexa\Contracts\ProductCatalog\Local\Values\ProductType\AssignAttributeDefinitionStruct;
711
use Ibexa\Contracts\ProductCatalog\ProductTypeServiceInterface;
812
use Symfony\Component\Console\Command\Command;
913
use Symfony\Component\Console\Input\InputArgument;
@@ -18,11 +22,26 @@ final class ProductTypeCommand extends Command
1822

1923
private ProductTypeServiceInterface $productTypeService;
2024

21-
public function __construct(UserService $userService, PermissionResolver $permissionResolver, ProductTypeServiceInterface $productTypeService)
22-
{
25+
private LocalProductTypeServiceInterface $localProductTypeService;
26+
27+
private ContentTypeService $contentTypeService;
28+
29+
private AttributeDefinitionServiceInterface $attributeDefinitionService;
30+
31+
public function __construct(
32+
UserService $userService,
33+
PermissionResolver $permissionResolver,
34+
ProductTypeServiceInterface $productTypeService,
35+
LocalProductTypeServiceInterface $localProductTypeService,
36+
ContentTypeService $contentTypeService,
37+
AttributeDefinitionServiceInterface $attributeDefinitionService
38+
) {
2339
$this->userService = $userService;
2440
$this->permissionResolver = $permissionResolver;
2541
$this->productTypeService = $productTypeService;
42+
$this->localProductTypeService = $localProductTypeService;
43+
$this->contentTypeService = $contentTypeService;
44+
$this->attributeDefinitionService = $attributeDefinitionService;
2645
parent::__construct('doc:product_type');
2746
}
2847

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

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

63+
$productTypeCreateStruct = $this->localProductTypeService->newProductTypeCreateStruct(
64+
'digital_product',
65+
'eng-GB'
66+
);
67+
68+
$productTypeCreateStruct->setNames([
69+
'eng-GB' => 'Digital Product',
70+
'pol-PL' => 'Produkt Cyfrowy',
71+
]);
72+
73+
$productTypeCreateStruct->setVirtual(true);
74+
75+
$contentTypeCreateStruct = $productTypeCreateStruct->getContentTypeCreateStruct();
76+
77+
$marketingDescriptionFieldDefinition = $this->contentTypeService->newFieldDefinitionCreateStruct(
78+
'marketing_description',
79+
'ezstring'
80+
);
81+
$marketingDescriptionFieldDefinition->names = ['eng-GB' => 'Marketing Description'];
82+
$marketingDescriptionFieldDefinition->position = 100;
83+
$contentTypeCreateStruct->addFieldDefinition($marketingDescriptionFieldDefinition);
84+
85+
$sizeAttribute = $this->attributeDefinitionService->getAttributeDefinition('size');
86+
87+
$attributeAssignment = new AssignAttributeDefinitionStruct(
88+
$sizeAttribute,
89+
false,
90+
false
91+
);
92+
93+
$productTypeCreateStruct->setAssignedAttributesDefinitions([$attributeAssignment]);
94+
95+
$newProductType = $this->localProductTypeService->createProductType($productTypeCreateStruct);
96+
4497
$productType = $this->productTypeService->getProductType($productTypeIdentifier);
4598

4699
$output->writeln($productType->getName());

docs/api/rest_api/rest_api_reference/input/examples/product/catalog/product_types/POST/ProductType.json.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"_media-type": "application/vnd.ibexa.api.ProductType+json",
44
"identifier": "test_pt321",
55
"name": "New Product Type",
6+
"is_virtual": false,
67
"AttributeAssignmentList": [
78
{
89
"_media-type": "application/vnd.ibexa.api.AttributeAssignment+json",

docs/api/rest_api/rest_api_reference/input/examples/product/catalog/product_types/POST/ProductTypeCreate.json.example

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"is_required": false,
8484
"is_discriminator": true
8585
}
86-
]
86+
],
87+
"is_virtual": false
8788
}
88-
}
89+
}

docs/api/rest_api/rest_api_reference/input/examples/product/catalog/product_types/POST/ProductTypeView.json.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"_media-type": "application/vnd.ibexa.api.ProductType+json",
1616
"identifier": "climbing_shoe",
1717
"name": "New Product Type",
18+
"is_virtual": false,
1819
"AttributeAssignmentList": [
1920
{
2021
"_media-type": "application/vnd.ibexa.api.AttributeAssignment+json",

docs/api/rest_api/rest_api_reference/input/examples/product/catalog/product_types/id/GET/ProductType.json.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"_media-type": "application/vnd.ibexa.api.ProductType+json",
44
"identifier": "d_rope",
55
"name": "Dynamic ropes",
6+
"is_virtual": false,
67
"AttributeAssignmentList": []
78
}
8-
}
9+
}

docs/api/rest_api/rest_api_reference/input/ibexa-types.raml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4526,6 +4526,10 @@ ProductTypeCreate:
45264526
assigned_attributes:
45274527
type: array
45284528
items: ProductTypeAssignedAttribute
4529+
is_virtual:
4530+
type: boolean
4531+
required: false
4532+
description: 'Determines whether the product type is virtual (digital products) or physical. Defaults to false (physical).'
45294533

45304534
ProductTypeUpdateWrapper:
45314535
description: 'JSON object with only a ProductTypeUpdate property.'

docs/pim/pim_guide.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,17 @@ Before you can assign categories to products, you need to [enable product catego
7979

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

82+
### Virtual and physical products
83+
84+
Product types in [[= product_name =]] can be either virtual or physical:
85+
86+
- **Physical products** are tangible items that require shipping (for example: books, clothing, electronics).
87+
- **Virtual products** are items that don't require physical delivery (for example: software licenses, e-books, online courses, digital downloads, additional warranty, tickets for an event).
88+
89+
This product type property can affect the checkout process.
90+
A cart of only virtual products skips the [shipping step](shipping_management.md) during checkout.
91+
To learn more about working with virtual products, see [Virtual products]([[= user_doc =]]/pim/create_virtual_product/) in the User Documentation.
92+
8293
### Currencies
8394

8495
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.

docs/pim/product_api.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,75 @@ You can retrieve the tags (corresponding to attribute values) of assets with the
105105

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

108+
### Creating product types
109+
110+
To create a product type, use [`LocalProductTypeServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalProductTypeServiceInterface.html).
111+
112+
First, create a product type struct with `LocalProductTypeServiceInterface::newProductTypeCreateStruct()`, providing the identifier and main language code:
113+
114+
``` php
115+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 62, 66) =]]
116+
```
117+
118+
You can set names in multiple languages by using `setNames()`:
119+
120+
``` php
121+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 67, 71) =]]
122+
```
123+
124+
To create a virtual product type (for products that don't require shipping), use `setVirtual()`:
125+
126+
``` php
127+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 72, 73) =]]
128+
```
129+
130+
#### Adding field definitions
131+
132+
To add custom field definitions to the product type, use `getContentTypeCreateStruct()` to access the underlying content type struct.
133+
For more information about working with content types, see [Adding content types](../content_management/content_api/managing_content.md#adding-content-types).
134+
135+
``` php
136+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 76, 83) =]]
137+
```
138+
139+
#### Assigning attributes
140+
141+
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.
142+
143+
First, retrieve the attribute definition by using [`AttributeDefinitionServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-AttributeDefinitionServiceInterface.html):
144+
145+
``` php
146+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 84, 85) =]]
147+
```
148+
149+
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):
150+
151+
``` php
152+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 86, 93) =]]
153+
```
154+
155+
For more information about working with attributes through PHP API, see [Attributes](#attributes).
156+
157+
#### Storing new product type
158+
159+
Finally, create the product type with `LocalProductTypeServiceInterface::createProductType()`:
160+
161+
``` php
162+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 94, 95) =]]
163+
```
164+
165+
### Getting product types
166+
108167
Get a product type object by using `ProductTypeServiceInterface::getProductType()`:
109168

110169
``` php
111-
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 43, 44) =]]
170+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 96, 97) =]]
112171
```
113172

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

116175
``` php
117-
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 47, 52) =]]
176+
[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 100, 105) =]]
118177
```
119178

120179
## Product availability

0 commit comments

Comments
 (0)